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的方式來進行查詢

相關文章
相關標籤/搜索