Hibernate使用Criteria去重distinct+分頁


寫在前面:

  最近在項目中使用了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的方式來進行查詢

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM