但是又會比較牴觸它,因爲對它的不熟悉,寫複雜查詢可能會不順手,一個子查詢也可能會很麻煩。
今天我用半天時間與大家分享Criteria查詢裏面彎路比較多的結果集distinct,這個在HQL裏面很簡單,但在Criteria查詢還真是頭疼,網上的文章也是很模糊而且討論的比較片面,我希望通過這篇文章讓大家少走彎路,多用Criteria查詢,少用HQL拼字符串。呵呵。
Criteria的結果集最常用分兩種:對象List、List<Object[]>(投影查詢),這兩種查詢結果的distinct處理的方式也是不一樣的。稍後會分別討論。
本文用到模型類:
Device.java
====================================
- @Entity
- @Table(name = "DEVICE")
- public class Device extends Maintainable {
- private Long id;
- private String name;
- private NodeCabinet nodeCabinet;// 所屬機櫃
- // setter getter method ...
- }
1. 基本知識:
1.1 Criteria不支持distinct對象結果集嗎?
re: Criteria通過setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)方法對查詢後結果進行排重,請注意,這種方式是先查詢出可能重複的記錄然後根據每個對象的equals方法進行排重,如果不需要分頁,而且你的查詢結果集很小的話,可以使用這種方式distinct結果集。
warning:
- 1. 要排重的對象要實現equals方法。
- 2. 不能進行分頁處理,因爲是先查詢後distinct,結果會不準確。
- 3. 查詢處理的結果集太大的話,可能存在性能問題,相同記錄會查詢多次。
示例代碼 1-1:
- Criteria c = manager.createCriteria(Device.class);
- .....
- criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY)
- List result = c.list();
1.2 Criteria如何進行投影查詢我需要的幾個字段?
re:Criteria通過設置projectionList就可以只查詢指定字段。
warning:Criteria投影查詢出來的結果集格式是這樣的:List<Object[]> 前臺遍歷集合的時候需要使用數組下標訪問數據。
示例代碼 1-2:
- Criteria c = manager.createCriteria(Device.class);
- .....
- ProjectionList projectionList = Projections.projectionList();
- projectionList.add(Projections.property("id"));
- projectionList.add(Projections.property("name"));
- c.setProjection(projectionList); //生成如下SQL: select id, name from ....
- List result = c.list();
2. Criteria投影distinct查詢
2.1 Criteria投影distinct查詢
Criteria對投影的支持比返回對象的方式支持的好很多。以下是樣例代碼,與比示例1-2代碼只有一行差別:
示例代碼 2-1:
- Criteria c = manager.createCriteria(Device.class);
- .....
- ProjectionList projectionList = Projections.projectionList();
- projectionList.add(Projections.property("id"));
- projectionList.add(Projections.property("name"));
- c.setProjection(Projections.distinct(projectionList)); // >>>> 這裏差別 生成如下SQL: select distinct id, name from ....
- List result = c.list();
2.2 分頁情況下Criteria查詢如何計算total records count
投影情況下如何計算distinct後分頁total records count?
re:Criteria通過Projection計算count。先算count然後在投影。計算count的可以封裝到單獨查詢方法裏。
示例代碼:
- Criteria c = manager.createCriteria(Device.class);
- .....
- criteria.setProjection(Projections.countDistinct("id")); // select count(distcint id) from ...
- Integer totalCount = (Integer) criteria.uniqueResult();
- ProjectionList projectionList = Projections.projectionList();
- projectionList.add(Projections.property("id"));
- projectionList.add(Projections.property("name"));
- c.setProjection(Projections.distinct(projectionList)); // 生成如下SQL: select distinct id, name from ....
- List result = c.list();