今天作项目的过程当中发现,多表查询的时候若是使用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的上次查询条件,若是不清除,将会致使上次的查询条件和下次的查询条件合并到了一块儿。