写在前面:

  最近在项目中使用了Criteria的分页查询,当查询的数据没有重复的记录还好,但是当数据有关联并出现重复记录的时候,就要去重,那么就会出现查询的记录数与实际的不一致的问题。这里也记录一下解决的办法。

  这里只是拿学生Student表与班级来举例,没有经过测试

  1.查询全部的数据,不进行分页处理,使用distinct去重完全是可以的,代码大致如下:

/**
* 查询所有的学生 不分页去重
* @return
* @throws Exception
*/
public List<Student> listAllStudent() throws Exception {
Session session = this.getCurrentSession();
Criteria criteria = session.createCriteria(Student.class);
//去重 不分页
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
List<Student> list = criteria.list();
return list;
}

  2.查询全部的数据,但是要分页查询。先来看下出问题的代码,大致如下:

   /**
* 查询所有的学生 分页去重
* 问题代码 此种方式当有复杂的关联关系时 查出来的数据记录会与实际的不一致
* @return
* @throws Exception
*/
public List<Student> listAllStudent2() throws Exception {
Session session = this.getCurrentSession();
Criteria criteria = session.createCriteria(Student.class);
//去重 会出现数据记录数不一致问题
criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
//分页
List<Student> list = criteria.setFirstResult(0).setMaxResults(5).list();
return list;
}

  一般情况下,我们都会使用上面的代码,但是经过数据的测试就会发现,分页后查询出来的代码虽然去重了,但是数据的记录条数会出问题,与实际的并不一致。之所以会出现这样的问题,是因为,上面的代码的执行顺序是查询出所有符合条件的记录,然后是先分页,分页分好了,再去重,那如果查询出来的第一页数据有3条,里面有两个记录是重复的,那么经过去重后,第一页显示出来的数据就只有2条;而我们正常分页去重的顺序应该是,先查询出所有符合条件的记录,然后去重,最后才是在分页。

  下面就提供一种解决方案。大致的代码如下:

 /**
* 查询所有的学生 分页去重 正确的打开方式
* @return
* @throws Exception
*/
public List<Student> listAllStudent3() throws Exception {
Session session = this.getCurrentSession();
Criteria criteria = session.createCriteria(Student.class);
//1.分页查询出所有的Student的唯一标识studentId
criteria.setProjection(Projections.distinct(Property.forName("studentId")));
List<String> studentIdList = criteria.setFirstResult(0).setMaxResults(5).list();
//2.重新构建criteria查询
Criteria criteria2 = session.createCriteria(Student.class);
List<Student> resultList = new ArrayList<Student>();
//3.查询所有studentId在studentIdList里的Student
if(studentIdList.size()>0){
criteria2.add(Restrictions.in("studentId",studentIdList));
//这里才使用去重 不需要再次分页了
criteria2.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
resultList = criteria2.list();
}
return resultList;
}

  上面代码基本就完成了使用Criteria查询,并且可以分页,可以去重。大致步骤可以分为三个部分:

    举例:表a,表b,两个表有关联关系,现在要查询出所有符合条件的a记录,并且使用分页查询

    1.分页查询出所有的a的唯一标识属性集合list,注意这里要进行分页

    2.再次重新构建criteria查询

    3.查询出所有a的唯一属性包含在list集合中的a记录,并去重

  当然了,这只是个大致的步骤,具体的代码还要根据自己的项目来看,对了,还要稍微注意下,当Criteria查询使用别名的时候,记得选择合适自己项目的连接方式,比如,当表a中有外键与表b关联,当a的外键是null的时候,要想查询此条记录出来,要使用表a左外连接表b的方式来进行查询

Hibernate使用Criteria去重distinct+分页的更多相关文章

  1. Hibernate 中Criteria Query查询详解【转】

    当查询数据时,人们往往需要设置查询条件.在SQL或HQL语句中,查询条件常常放在where子句中.此外,Hibernate还支持Criteria查询(Criteria Query),这种查询方式把查询 ...

  2. 分享知识-快乐自己:Hibernate 中Criteria Query查询详解

    1):Hibernate 中Criteria Query查询详解 当查询数据时,人们往往需要设置查询条件.在SQL或HQL语句中,查询条件常常放在where子句中. 此外,Hibernate还支持Cr ...

  3. mysql 查询去重 distinct

    mysql 查询去重 distinct   待完善内容..

  4. Atitit.Hibernate中Criteria 使用总结and 关联查询 and 按照子对象查询 o9o

    Atitit.Hibernate中Criteria 使用总结and 关联查询 and 按照子对象查询 o9o 1. Criteria,,Criterion ,, 1 <2. 主要的对象黑头配置磊 ...

  5. Hibernate之Criteria的完整用法

    Criteria的完整用法 QBE (Query By Example) Criteria cri = session.createCriteria(Student.class); cri.add(E ...

  6. Atitit.Hibernate于Criteria 使用汇总and 关系查询 and 按照子对象查询 o9o

    Atitit.Hibernate于Criteria 使用总结and 关联查询 and 依照子对象查询 o9o 1. Criteria,,Criterion ,, 1 <2. 基本的对象黑头配置磊 ...

  7. 转:Hibernate中Criteria和DetachedCriteria的完整用法

    原文地址:http://blog.sina.com.cn/s/blog_667528fd0100rkrf.html 设计上可以灵活的根据 Criteria 的特点来方便地进行查询条件的组装.现在对 H ...

  8. Hibernate中Criteria的完整用法2

    Criteria的完整用法 QBE (Query By Example) Criteria cri = session.createCriteria(Student.class); cri.add(E ...

  9. Hibernate中Criteria的完整用法

    1,CriteriaHibernate 设计了 CriteriaSpecification 作为 Criteria 的父接口,下面提供了 Criteria和DetachedCriteria .2,De ...

随机推荐

  1. FluentAPI深入

    1.  HasMaxLenght 设定字段得最大长度: static void Main(string[] args) { using (TestDbContext ctx = new TestDbC ...

  2. 课时1:我和python的第一次亲密接触

    目录: 一.Python3的下载与安装 二.从IDIE启动Python 三.尝试点新的东西 四.为什么会这样? 五.课时01课后习题及答案 ============================== ...

  3. ocrosoft Contest1316 - 信奥编程之路~~~~~第三关 问题 x: 十进制到二进制的转换

    http://acm.ocrosoft.com/problem.php?cid=1316&pid=49 题目描述 把十进制到二进制的转换. 输入 234 输出 11101010 样例输入 23 ...

  4. 使用Bootstrap框架的HTML5页面模板

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. luajit的字节码

    http://blog.csdn.net/zzz3265/article/details/41146569 这里写出了luajit的字节码

  6. npm理解

    NPM就是一个下载器,通过它可以下载到几乎所有你需要的代码资源.它的成功,包括如下几个方面: 海量资源:NPM背后有数以万计的开源免费模块. 高效利用:作为开发者,只需要敲几个简单的命令就可以将这些开 ...

  7. [洛谷P3805]【模板】manacher算法

    题目大意:给你一个字符串,求出它的最长回文字段 题解:$manacher$算法 卡点:$p$数组未开两倍空间 C++ Code: #include <cstdio> #include &l ...

  8. [Codeforces 1027 F] Session in BSU [并查集维护二分图匹配问题]

    题面 传送门 思路 真是一道神奇的题目呢 题目本身可以转化为二分图匹配问题,要求右半部分选择的点的最大编号最小的一组完美匹配 注意到这里左边半部分有一个性质:每个点恰好连出两条边到右半部分 那么我们可 ...

  9. BZOJ1296 [SCOI2009]粉刷匠 【dp】

    题目 windy有 N 条木板需要被粉刷. 每条木板被分为 M 个格子. 每个格子要被刷成红色或蓝色. windy每次粉刷,只能选择一条木板上一段连续的格子,然后涂上一种颜色. 每个格子最多只能被粉刷 ...

  10. Tomcat学习笔记(十)

    StandardWrapper容器 Context容器包含一个或者多个Wrapper实例,每个Wrapper实例表示一个具体的servlet定义. 方法调用序列 具体过程 (1)连接器创建reques ...