写在前面:

  最近在项目中使用了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. java5初学

    1.Eclipse快捷键 alt + / 代码提示,例如自动创建main方法ctrl + d 删除当前行ctrl + alt + up/down 复制当前行alt + up/down 交换行ctrl ...

  2. URAL 1732. Ministry of Truth ( KMP 多模式串匹配 )

    问在第一个串中删掉几个字符能否得到第二个串.注意在第二个串中不连续的单词在第一个串中也必须不连续. 一组数据: Input: abababbbbababbb aba ab Output: I HAVE ...

  3. J2EE的十三种技术——JNDI

    背景: 上一篇博客中介绍了J2EE的十三种技术之一--JDBC,主要用于提供了统一访问多种数据库的方式.这篇文章我们继续介绍J2EE的技术--JNDI. JNDI: Java Naming and D ...

  4. gulp (转)

    “1. 我为什么使用grunt: 2. 我为何放弃grunt转投gulp: 3. 我为何放弃gulp与grunt,转投npm scripts: 4. 我为何放弃前端” —— 司徒正美 前端(段子)界的 ...

  5. 【bzoj3585/bzoj3339】mex/Rmq Problem 莫队算法+分块

    原文地址:http://www.cnblogs.com/GXZlegend/p/6805283.html 题目描述 有一个长度为n的数组{a1,a2,...,an}.m次询问,每次询问一个区间内最小没 ...

  6. 利用反射修改final数据域

    当final修饰一个数据域时,意义是声明该数据域是最终的,不可修改的.常见的使用场景就是eclipse自动生成的serialVersionUID一般都是final的. 另外还可以构造线程安全(thre ...

  7. 刷题总结——Throw nails(hdu4393)

    题目: Problem Description The annual school bicycle contest started. ZL is a student in this school. H ...

  8. Eclipse 日文乱码怎么解决Shift_JIS

    https://jingyan.baidu.com/article/870c6fc325a691b03fe4beac.html Eclipse设置编码的地方主要有三处,这三处的设置都会影响中文的显示. ...

  9. js函数调用与声明 (for时注意)

    可以的: test();  // 直接function 方式声明的函数可以直接调用,后声明 function test(){} aa();   //error  var 方式声明的函数需先声明后调用v ...

  10. [ CodeVS冲杯之路 ] P3117

    不充钱,你怎么AC? 题目:http://codevs.cn/problem/3117/ 啊啊啊,基础的高精度乘法被我写得又臭又长,以后再来优化代码(DP着哪天能够把加减乘除全部写一边贴上来,哦对还有 ...