zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    Android开发总结
    LeakCanary原理分析
    机器学习
    Kivy 中文教程 实例入门 简易画板 (Simple Paint App):2. 实现绘图功能
    Python 零基础 快速入门 趣味教程 (咪博士 海龟绘图 turtle) 3. 循环
    Kivy 中文教程 实例入门 简易画板 (Simple Paint App):1. 自定义窗口部件 (widget)
    Python 零基础 快速入门 趣味教程 (咪博士 海龟绘图 turtle) 2. 变量
    Python 零基础 快速入门 趣味教程 (咪博士 海龟绘图 turtle) 1. 神秘朋友
    Python 零基础 快速入门 趣味教程 (咪博士 海龟绘图 turtle) 0. 准备工作
    远程显示(操作) 服务器 GUI 程序(图形化界面) (基于 X11 Forwarding + Centos + MobaXterm)
  • 原文地址:https://www.cnblogs.com/jepson6669/p/8875052.html
Copyright © 2011-2022 走看看