写在前面:

  最近在项目中使用了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. eclipse进阶功法

    先选择要操作的行,在同时按shift+alt+a,会将所选中的文字括起来,鼠标会变成十字图标,按住鼠标左键,在相应输入文字的位置上下拖动,会出现一个竖杠,此时即可开始输入文字了,并且所选中行都有.

  2. java开发环境的安装

    1.Java是一门面向对象的编程语言,由sun公司开发的,目前公司已经被oracle公司收购.那么作为一门编程语言,它有自己的编程环境.并不是你编写了java代码后,就能在任何平台上运行,它的运行有自 ...

  3. 1004 Counting Leaves (30 分)(树的遍历)

    给出一棵树,问每一层各有多少叶子节点 dfs遍历树 #include<bits/stdc++.h> using namespace std; vector<]; int n,m; i ...

  4. Android之SQLite总结

    SQLite 是一个轻量级的数据库,常用于各种嵌入式设备当中.android 提供了SQLiteOpenHelper的抽象类用于帮助开发数据库.在实际使用中经常定义一个类继承SQLiteOpenHel ...

  5. 爬虫:Scrapy9 - Feed exports

    实现爬虫时最经常提到的需求就是能合适的保存爬取到的数据,或者说,生成一个带有爬取数据的“输出文件”(通常叫“输出 feed”),来供其它系统使用. Scrapy 自带了 Feed 输出,并且支持多种序 ...

  6. golang中从一个日期开始往后增加一段时间

    废话少说上code, 这个是从当前日期开始,往后增加一个月时间 package main import ( "fmt" "time" ) func main() ...

  7. typescript语言

    百度百科:2013年6月19日,在经历了一个预览版之后微软正式发布了正式版TypeScript 0.9

  8. IDEA 14注册码

    用户: share密钥:78689-AFOCD-P3SDN-83DEC-BQ3UC-V6UK7用户: for密钥:13768-8VXX0-YL2BG-YBD88-2M3HN-CAOQ5用户: you密 ...

  9. KNN算法在保险业精准营销中的应用

    版权所有,可以转载,禁止修改.转载请注明作者以及原文链接. 一.KNN算法概述 KNN是Machine Learning领域一个简单又实用的算法,与之前讨论过的算法主要存在两点不同: 它是一种非参方法 ...

  10. 静态编译zsummerX

    下载 https://github.com/zsummer/zsummerX 下载 http://ftp.gnu.org/gnu/glibc/ ../configure --prefix=/home/ ...