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