• 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

  • 相关阅读:
    15、常量指针和指针常量区别?
    14、strlen和sizeof区别?
    12、变量声明和定义区别?
    10、宏定义和函数和typedef有何区别?
    hdoj--1495--非常可乐(搜索+隐式图)
    hdoj--2579--Dating with girls(2)(搜索+三维标记)
    poj--3630--Phone List(字典树+前缀判断)
    poj--2001--Shortest Prefixes(字典树)
    Huatuo's Medicine
    hdoj--2803--The MAX(水题)
  • 原文地址:https://www.cnblogs.com/jepson6669/p/8875052.html
Copyright © 2020-2023  润新知