Hibernate中criteria一对多关联查询时distinct的分页和数量问题
2017-04-28 01:01
274 查看
吐个槽:
hibernate Criteria 为何不能在结果集返回前就筛出重复,还不能分组,不能 DISTINCT, 否则返回单数据, 希望高手指点。
解决办法:
原文:
数据模型
班级:clazz(id,name,studentList)
学生:student(id,name,address,clazz)
经典查询
查询有地址在成都的班级信息,并分页显示。
一般情况下,以上的条件更多,也更复杂,且查询主体必须从班级入手。那么,使用Hibernate的criteria查询的话,一般情况下,编码如下:
单就逻辑本身,看似没有什么问题,且在数据较少(如没有分页数据时),会返回正确的结果。但是一旦出现分页数据时,你就会发现,分页数据是错的。表现结果为page对象所表现的数据总数明确不对,且每页所显示的数据也并不是分页信息中的20条,而是不确定的几条(明显少于默认的20条)。这就表明,在这个查询中,肯定有一步出问题了。
没错,在这个查询中,我们要求返回的主体为班级,即Clazz。但Hibernate出生的sql却并不能如我们所愿,它直接使用连接来组装sql语句,并尝试返回包括学生在类的一个复合对象,然后再组装成班级对象,最后根据集合信息进行distinct操作,最后就形成了不正确的结果。整个操作看起来如下所示:
看到以上的过程,你大概知道什么问题了吧。所使用setResultTransformer(distinct)并没有反映到所生成的sql中,而却是在取得结果后再进行。
此问题在:http://stackoverflow.com/questions/300491/how-to-get-distinct-results-in-hibernate-with-joins-and-row-based-limiting-pagi 也有提及。即如何在关联查询时返回distinct的主体信息。
有人会说,那就在criteria中加入类似distinct的查询条件,或者只让hibernate查询a.*吧。值得抱歉的是,值到现在hibernate并没有提供这样的功能。那么如何解决这个问题呢,在所引用的英文提问中,提到一种方式,就是使用 setProjection(Projections.distinctProperty(id))先把a的id查询出来。详细逻辑如下所示:
总共需要查询3次查询,第一步查总数,第二步查询结果所对应的主键id,第三步使用id再查询具体的对象信息。对于比较复杂的查询来说,这三步必不可少。然而对于像本方比较简单的查询,可以使用exists来代替innerJoin关联查询,这种方式可以避免在查询语句中查询出b.*。
通过这种将关联查询转化为exists子查询,可以确保在生成的select sql语句中,只会查询a.*。这就减少了查询结果,同时也满足我们所需要的结果。
如果是简单的条件查询,使用hql肯定会更简单,同时也能够控制所生成的sql语句。当只能使用criteria进行构建查询时,为保证结果的正确性,尽量使用exists式的子查询,可以保证查询对象的尽量少,也可以保证结果的正确性。特别是当需要从一方关联多的一方进行关联查询时,尤其需要注意返回结果的正确性。
hibernate Criteria 为何不能在结果集返回前就筛出重复,还不能分组,不能 DISTINCT, 否则返回单数据, 希望高手指点。
解决办法:
原文:
数据模型
班级:clazz(id,name,studentList)
学生:student(id,name,address,clazz)
经典查询
查询有地址在成都的班级信息,并分页显示。
一般情况下,以上的条件更多,也更复杂,且查询主体必须从班级入手。那么,使用Hibernate的criteria查询的话,一般情况下,编码如下:
没错,在这个查询中,我们要求返回的主体为班级,即Clazz。但Hibernate出生的sql却并不能如我们所愿,它直接使用连接来组装sql语句,并尝试返回包括学生在类的一个复合对象,然后再组装成班级对象,最后根据集合信息进行distinct操作,最后就形成了不正确的结果。整个操作看起来如下所示:
此问题在:http://stackoverflow.com/questions/300491/how-to-get-distinct-results-in-hibernate-with-joins-and-row-based-limiting-pagi 也有提及。即如何在关联查询时返回distinct的主体信息。
有人会说,那就在criteria中加入类似distinct的查询条件,或者只让hibernate查询a.*吧。值得抱歉的是,值到现在hibernate并没有提供这样的功能。那么如何解决这个问题呢,在所引用的英文提问中,提到一种方式,就是使用 setProjection(Projections.distinctProperty(id))先把a的id查询出来。详细逻辑如下所示:
如果是简单的条件查询,使用hql肯定会更简单,同时也能够控制所生成的sql语句。当只能使用criteria进行构建查询时,为保证结果的正确性,尽量使用exists式的子查询,可以保证查询对象的尽量少,也可以保证结果的正确性。特别是当需要从一方关联多的一方进行关联查询时,尤其需要注意返回结果的正确性。
相关文章推荐
- hibernate一对多关联查询去重 criteria设置 解决分页条数不正确的问题
- Hibernate Criteria 多层次查询关联问题
- Hibernate Criteria 多层次查询关联问题
- hibernate中Criteria的DISTINCT查询问题的解决方法
- Hibernate Criteria 多层次查询关联问题 HibernateJava
- Hibernate Criteria 多层次查询关联问题
- Hibernate用Criteria查询时使用Distinct方法去除重复数据
- 关于hibernate纯sql查询返回结果集的问题(hbm.xml中不写多表关联)
- hibernate关联表查询返回关系表数据问题
- hibernate 一对多 分页 criteria 查询
- Hibernate的查询 标准(Criteria)查询 分页、单个记录、排序
- mysql一对多关联查询分页错误问题的解决方法
- 使用Hibernate criteria进行分页查询时,如何实现一次查询取得总记录数和分页后结果集
- 关于hibernate纯sql查询返回结果集的问题(hbm.xml中不写多表关联)
- 关于hibernate纯sql查询返回结果集的问题(hbm.xml中不写多表关联)
- 应用Hibernate3的DetachedCriteria实现分页查询
- Hibernate3的DetachedCriteria实现分页查询
- 应用Hibernate3的DetachedCriteria实现分页查询
- hibernate查询之Criteria实现分页方法(GROOVY语法)
- 关于Hibernate中fatch=eager的bag集合(一个java List)使用Criteria查询出现重复记录的问题