Criteria 提供完全面向對象的查詢構建方式,無需編寫 SQL/HQL 字串,適合動態查詢條件、分頁、排序場景。Hibernate 5.2+ 推薦使用 JPA CriteriaBuilder,但傳統 org.hibernate.Criteria 仍廣泛用於維護專案。
Session session = sessionFactory.openSession();
Criteria criteria = session.createCriteria(User.class);
criteria.add(Restrictions.eq("name", "shun")); // WHERE name = 'shun'
List users = criteria.list();
核心類:Restrictions(Hibernate 3+ 取代 Expression)提供 eq, ne, gt, ge, lt, le, like, between, in, isNull 等條件工廠方法。
解決 Session 關閉後無法復用 Criteria 的問題,適合 Service 層構建查詢、DAO 層執行。
// 構建查詢(無需 Session)
DetachedCriteria dc = DetachedCriteria.forClass(User.class);
dc.add(Restrictions.eq("name", "shun"));
// 執行查詢(綁定 Session)
Session session = sessionFactory.openSession();
List users = dc.getExecutableCriteria(session).list();
session.close();
// 另一個 Session 復用同一查詢
Session session2 = sessionFactory.openSession();
List users2 = dc.getExecutableCriteria(session2).list();
// 子查詢:計算平均年齡
DetachedCriteria avgAge = DetachedCriteria.forClass(User.class);
avgAge.setProjection(Projections.avg("age"));
// 主查詢:年齡大於平均值
Criteria criteria = session.createCriteria(User.class);
criteria.add(Subqueries.propertyGt("age", avgAge)); // age > (SELECT AVG(age) FROM User)
List users = criteria.list();
Projections 常用方法:avg, sum, max, min, count, countDistinct, groupProperty, projectionList。
Criteria criteria = session.createCriteria(User.class);
// 分頁:從第 10 筆開始,取 20 筆
criteria.setFirstResult(10);
criteria.setMaxResults(20);
// 排序:年齡降序
criteria.addOrder(Order.desc("age")); // 或 Order.asc("name")
// 分組:按年齡分組
criteria.setProjection(Projections.groupProperty("age")); // SELECT age FROM User GROUP BY age
// 組合投影:分組 + 計數
ProjectionList pl = Projections.projectionList();
pl.add(Projections.groupProperty("age"));
pl.add(Projections.rowCount());
criteria.setProjection(pl); // SELECT age, COUNT(*) FROM User GROUP BY age
// 一對多:User -> Orders
Criteria criteria = session.createCriteria(User.class);
criteria.createAlias("orders", "o"); // 內連接
criteria.add(Restrictions.eq("o.status", "SHIPPED"));
// 左外連接:查詢無訂單用戶
criteria.createAlias("orders", "o", Criteria.LEFT_JOIN);
criteria.add(Restrictions.isNull("o.id"));
// 返回 Map 而非 Entity
criteria.setProjection(Projections.projectionList()
.add(Projections.property("id"), "id")
.add(Projections.property("name"), "name"));
criteria.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
List
criteria.setCacheable(true); // 啟用二級快取
criteria.setCacheRegion("userQueryCache"); // 指定快取區域
| 方法 | SQL 等價 | 說明 |
|---|---|---|
| eq(property, value) | property = value | 等於 |
| ne(property, value) | property != value | 不等於 |
| gt/ge/lt/le | > / >= / < / <= | 比較 |
| like(property, value) | property LIKE value | 模糊匹配,支援 % _ |
| between(property, lo, hi) | property BETWEEN lo AND hi | 範圍 |
| in(property, collection) | property IN (...) | 集合包含 |
| isNull/isNotNull | IS NULL / IS NOT NULL | 空值判斷 |
| and/or(conjunction...) | AND / OR | 邏輯組合 |