首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Hibernate HQL 與 Criteria API 完整查詢指南:從入門到進階

     編輯:Java 相關知識

HQL:面向物件的查詢語言

HQL (Hibernate Query Language) 針對實體物件與屬性操作,而非資料表與欄位。最終由 Hibernate 轉換為 SQL 執行,具備資料庫可攜性與緩存策略優勢。

基本查詢結構

// 完整載入實體
FROM Employee
FROM com.company.model.Employee  // 全限定名

// 別名 (AS 可省略)
FROM Employee AS e
FROM Employee e

// 選取特定屬性 (回傳 List<Object[]> 或 List<String>)
SELECT e.firstName, e.salary FROM Employee e

// 條件過濾
FROM Employee e WHERE e.salary > 5000 AND e.department.name = 'IT'

// 排序
FROM Employee e ORDER BY e.salary DESC, e.hireDate ASC

// 分組聚合
SELECT e.department.name, AVG(e.salary), COUNT(*)
FROM Employee e GROUP BY e.department.name
HAVING COUNT(*) > 5

參數綁定:防止注入、提升效能

// 命名參數 (推薦)
String hql = "FROM Employee e WHERE e.salary > :minSal AND e.department = :dept";
Query query = session.createQuery(hql);
query.setParameter("minSal", 5000);
query.setParameter("dept", deptEntity);

// 位置參數 (從 0 開始)
query.setParameter(0, 5000);

分頁查詢

Query query = session.createQuery("FROM Employee e ORDER BY e.id");
query.setFirstResult(0);   // 起始索引
query.setMaxResults(20);   // 每頁筆數
List<Employee> page = query.list();

批量更新/刪除 (HQL 3.0+)

// 更新
String hql = "UPDATE Employee e SET e.salary = e.salary * 1.1 WHERE e.department.id = :deptId";
int updated = session.createQuery(hql)
    .setParameter("deptId", 1)
    .executeUpdate();

// 刪除
String hql = "DELETE FROM Employee e WHERE e.status = 'LEFT'";
int deleted = session.createQuery(hql).executeUpdate();

Criteria API:型別安全的程式化查詢

基本結構

CriteriaBuilder cb = session.getCriteriaBuilder();
CriteriaQuery<Employee> cq = cb.createQuery(Employee.class);
Root<Employee> root = cq.from(Employee.class);

// 選取全部
cq.select(root);

// 條件謂詞
Predicate salaryGt = cb.gt(root.get("salary"), 5000);
Predicate deptEq = cb.equal(root.get("department").get("id"), 1);
cq.where(cb.and(salaryGt, deptEq));

// 排序
cq.orderBy(cb.desc(root.get("salary")), cb.asc(root.get("hireDate")));

// 執行
List<Employee> result = session.createQuery(cq).getResultList();

常用 Restrictions (Hibernate 5 旧 API 兼容)

方法對應 SQL範例
eq=Restrictions.eq("status", "ACTIVE")
gt/ge/lt/le> / ≥ / < / ≤Restrictions.gt("age", 18)
like/ilikeLIKE (不分大小寫)Restrictions.like("name", "John%")
betweenBETWEENRestrictions.between("salary", 3000, 8000)
in/notInIN / NOT INRestrictions.in("id", ids)
isNull/isNotNullIS NULLRestrictions.isNull("deletedAt")
and/orAND / ORRestrictions.or(c1, c2)

投影與聚合

CriteriaQuery<Object[]> cq = cb.createQuery(Object[].class);
Root<Employee> root = cq.from(Employee.class);

// 聚合函數
cq.multiselect(
    cb.count(root),                    // 總筆數
    cb.avg(root.get("salary")),        // 平均薪資
    cb.max(root.get("salary")),        // 最高薪資
    cb.sum(root.get("salary")),        // 薪資總和
    cb.countDistinct(root.get("dept")) // 部門數
);

分頁與排序

TypedQuery<Employee> query = session.createQuery(cq);
query.setFirstResult(0);
query.setMaxResults(10);

進階技巧與最佳實踐

  1. Fetch 策略:使用 JOIN FETCH (HQL) 或 fetch() (Criteria) 解決 N+1 問題
  2. 唯一結果:uniqueResult() / getSingleResult() 配合異常處理
  3. 鎖定模式:query.setLockMode(LockMode.PESSIMISTIC_WRITE) 實現悲觀鎖
  4. 快取查詢:query.setCacheable(true) 配合二級快取
  5. 原生 SQL:複雜報表查詢用 createNativeQuery() 配合 @SqlResultSetMapping

總結

HQL 適合靜態、可讀性要求高的查詢;Criteria API 勝在動態組裝、型別安全、IDE 重構支援。現代 Hibernate (5.2+) 推薦使用 JPA 標準 CriteriaBuilder,舊版 Criteria 逐步淘汰。掌握兩者並根據場景選擇,是高效資料存取的關鍵。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved