今天作項目的過程當中發現,多表查詢的時候若是使用hibernate的DetachedCriteria離線查詢方式的時候,html
在多表關聯的時候咱們須要使用別名的方式去實現。java
可是代碼運行的過程當中拋出了下面的異常:ajax
以前出現異常的代碼:ide
public String pageQuery() throws Exception { DetachedCriteria dc = pageBean.getDetachedCriteria(); //動態添加過濾條件 String addresskey = model.getAddresskey(); if(StringUtils.isNotBlank(addresskey)){ //添加過濾條件,根據地址關鍵字模糊查詢 dc.add(Restrictions.like("addresskey", "%"+addresskey+"%")); } Region region = model.getRegion(); if(region != null){ String province = region.getProvince(); String city = region.getCity(); String district = region.getDistrict(); dc.createAlias("region", "r"); //第一次運行不會出錯,可是第二次運行就會報錯,由於以前已經存在了和它同樣的別名,頁面又是經過ajax請求的,不會刷新
if(StringUtils.isNotBlank(province)){ //添加過濾條件,根據省份模糊查詢-----多表關聯查詢,使用別名方式實現 //參數一:分區對象中關聯的區域對象屬性名稱 //參數二:別名,能夠任意 dc.add(Restrictions.like("r.province", "%"+province+"%")); } if(StringUtils.isNotBlank(city)){ //添加過濾條件,根據市模糊查詢-----多表關聯查詢,使用別名方式實現 //參數一:分區對象中關聯的區域對象屬性名稱 //參數二:別名,能夠任意 dc.add(Restrictions.like("r.city", "%"+city+"%")); } if(StringUtils.isNotBlank(district)){ //添加過濾條件,根據區模糊查詢-----多表關聯查詢,使用別名方式實現 //參數一:分區對象中關聯的區域對象屬性名稱 //參數二:別名,能夠任意 dc.add(Restrictions.like("r.district", "%"+district+"%")); } } subareaService.pageQuery(pageBean); this.java2Json(pageBean, new String[]{"currentPage","detachedCriteria","pageSize", "decidedzone","subareas"}); return NONE; }
經過查閱資料發現:用DetachedCriteria或者Criteria,使用CreateAlias時,若是第2個參數alias與以前添加的重複,則會報系統異常,函數
然而遺憾的是咱們的DetachedCriteria和Criteria並無提供排除這種重複的方法。this
要想在不修改Hibernate代碼的前提下,解決這個問題,咱們可使用JAVA的反射類解決該問題。spa
下面提供兩個函數,用於判斷path和alias是否已經添加。hibernate
private boolean existAlias(Criteria c, String path, String alias) { Iterator itm = ((CriteriaImpl) c).iterateSubcriteria(); while (itm.hasNext()) { Subcriteria sub = (Subcriteria) itm.next(); if (alias.equals(sub.getAlias()) || path.equals(sub.getPath())) { return true; } } return false; } private boolean existAlias(DetachedCriteria c, String path, String alias) { Class clazz = c.getClass(); try { Field field = clazz.getDeclaredField("criteria"); field.setAccessible(true); CriteriaImpl ci; ci = (CriteriaImpl) field.get(c); return existAlias(ci, path, alias); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } return false; }
而後在以前的代碼中調用提供的方法,並作以下修改能夠解決問題code
public String pageQuery() throws Exception { DetachedCriteria dc = pageBean.getDetachedCriteria(); //每一次分頁查詢的時候應該先清除以前的條件 // 動態添加過濾條件 String addresskey = model.getAddresskey(); if (StringUtils.isNotBlank(addresskey)) { // 添加過濾條件,根據地址關鍵字模糊查詢 dc.add(Restrictions.like("addresskey", "%" + addresskey + "%")); } Region region = model.getRegion(); if (region != null) { String province = region.getProvince(); String city = region.getCity(); String district = region.getDistrict(); //建立別名以前須要判斷別名是否存在。 boolean existAlias = existAlias(dc,null,"r"); if(!existAlias){//不存在就建立 dc.createAlias("region", "r"); } if (StringUtils.isNotBlank(province)) { // 添加過濾條件,根據省份模糊查詢-----多表關聯查詢,使用別名方式實現 // 參數一:分區對象中關聯的區域對象屬性名稱 // 參數二:別名,能夠任意 dc.add(Restrictions.like("r.province", "%" + province + "%")); } if (StringUtils.isNotBlank(city)) { // 添加過濾條件,根據市模糊查詢-----多表關聯查詢,使用別名方式實現 // 參數一:分區對象中關聯的區域對象屬性名稱 // 參數二:別名,能夠任意 dc.add(Restrictions.like("r.city", "%" + city + "%")); } if (StringUtils.isNotBlank(district)) { // 添加過濾條件,根據區模糊查詢-----多表關聯查詢,使用別名方式實現 // 參數一:分區對象中關聯的區域對象屬性名稱 // 參數二:別名,能夠任意 dc.add(Restrictions.like("r.district", "%" + district + "%")); } } subareaService.pageQuery(pageBean); this.java2Json(pageBean, new String[] { "currentPage", "detachedCriteria", "pageSize", "decidedzone", "subareas" }); return NONE; }
別名重複問題以後,咱們還須要解決的問題就是:htm
如何清除hibernate的上次查詢條件,若是不清除,將會致使上次的查詢條件和下次的查詢條件合併到了一塊兒。