Hibernate使用Criteria去重distinct+分页

写在前面:session

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

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

  1.查询所有的数据,不进行分页处理,使用distinct去重彻底是能够的,代码大体以下:spa

/**
     * 查询全部的学生 不分页去重
     * @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.查询所有的数据,可是要分页查询。先来看下出问题的代码,大体以下:code

   /**
     * 查询全部的学生  分页去重
     * 问题代码 此种方式当有复杂的关联关系时 查出来的数据记录会与实际的不一致
     * @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条;而咱们正常分页去重的顺序应该是,先查询出全部符合条件的记录,而后去重,最后才是在分页。orm

  下面就提供一种解决方案。大体的代码以下:blog

 /**
     * 查询全部的学生 分页去重  正确的打开方式
     * @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查询,而且能够分页,能够去重。大体步骤能够分为三个部分:get

    举例:表a,表b,两个表有关联关系,如今要查询出全部符合条件的a记录,而且使用分页查询it

    1.分页查询出全部的a的惟一标识属性集合list,注意这里要进行分页io

    2.再次从新构建criteria查询

    3.查询出全部a的惟一属性包含在list集合中的a记录,并去重

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

相关文章
相关标签/搜索