org.hibernate.QueryException: duplicate alias: r hibernate别名重复问题解决

今天做项目的过程中发现,多表查询的时候如果使用hibernate的DetachedCriteria离线查询方式的时候,

在多表关联的时候我们需要使用别名的方式去实现。

但是代码运行的过程中抛出了下面的异常:

之前出现异常的代码:

    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并没有提供排除这种重复的方法。

要想在不修改Hibernate代码的前提下,解决这个问题,我们可以使用JAVA的反射类解决该问题。

 

下面提供两个函数,用于判断path和alias是否已经添加。

  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;
    }

然后在之前的代码中调用提供的方法,并做如下修改可以解决问题

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;
    }

 别名重复问题之后,我们还需要解决的问题就是:

如何清除hibernate的上次查询条件,如果不清除,将会导致上次的查询条件和下次的查询条件合并到了一起。

具体参见:http://www.cnblogs.com/jepson6669/p/8876920.html

 

转载于:https://www.cnblogs.com/jepson6669/p/8875052.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值