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

Hibernate 兩大查詢方式深度對比:HQL vs Criteria Query

     編輯:Java 相關知識

查詢方式概覽

維度HQL (Hibernate Query Language)Criteria Query
風格類 SQL 字串,面向物件程式化 API,型別安全
編譯時檢查無(執行時解析)有(IDE 智慧提示、重構支援)
動態查詢構建字串拼接困難、易注入條件組合靈活(Criterion、Projections)
投影/聚合SELECT 子句直觀Projections API 較冗長
分頁/排序Query.setFirstResult/MaxResults、ORDER BYCriteria.setFirstResult/MaxResults、Order.asc/desc
適用場景靜態、複雜、報表類查詢動態條件、搜尋表單、通用 DAO

HQL 核心語法詳解

1. 基本查詢

FROM Cat                                    -- 所有 Cat 實例
FROM Cat AS cat                             -- 別名(建議)
FROM Cat cat                                -- AS 可省略
FROM Cat cat, Dog dog                       -- 笛卡兒積
FROM Cat cat INNER JOIN cat.kittens kitten  -- 關聯導航

2. 連接類型

INNER JOIN      -- 僅匹配雙方
LEFT OUTER JOIN -- 左表全保留,右表無匹配則 null
RIGHT OUTER JOIN-- 右表全保留
FULL JOIN       -- 雙方全保留(資料庫支援度有限)

範例:員工-部門

-- INNER JOIN:僅有部門的員工
SELECT e.id, e.name, d.name FROM Employee e JOIN e.department d

-- LEFT JOIN:所有員工,無部門者 department 欄位為 null
SELECT e.id, e.name, d.name FROM Employee e LEFT JOIN e.department d

3. SELECT 子句與投影

SELECT e.name FROM Employee e WHERE e.name LIKE 'J%'
SELECT e.id, e.name, d.id, d.name FROM Employee e RIGHT JOIN e.department d
SELECT COUNT(DISTINCT e.name), COUNT(e) FROM Employee e
SELECT AVG(e.salary), MAX(e.salary) FROM Employee e GROUP BY e.department

4. 多型查詢

FROM Animal a          -- 回傳 Animal 及所有子類 (Cat, Dog...)
FROM java.lang.Object o-- 回傳所有持久化實體(慎用,效能極差)

5. 參數綁定

-- 位置參數
List list = session.find("FROM Employee e WHERE e.name = ?", name, Hibernate.STRING);

-- 命名參數(推薦,可讀性佳)
Query q = session.createQuery("FROM Employee e WHERE e.name = :name");
q.setString("name", "Jplateau");
Iterator it = q.iterate();

6. 子查詢

FROM Cat fatcat WHERE fatcat.weight > (SELECT AVG(cat.weight) FROM DomesticCat cat)

Criteria Query 實戰

Criteria criteria = session.createCriteria(User.class);
criteria.add(Expression.eq("name", "Erica"));
criteria.add(Expression.eq("sex", Integer.valueOf(1)));

// 動態條件組合
if (searchForm.getName() != null) {
    criteria.add(Expression.like("name", "%" + searchForm.getName() + "%"));
}
if (searchForm.getMinAge() != null) {
    criteria.add(Expression.ge("age", searchForm.getMinAge()));
}

// 投影與聚合
criteria.setProjection(Projections.projectionList()
    .add(Projections.count("id"), "total")
    .add(Projections.groupProperty("department"), "dept"));

// 分頁排序
criteria.addOrder(Order.desc("createTime"));
criteria.setFirstResult(0);
criteria.setMaxResults(20);

List results = criteria.list();

進階主題

Named Query 集中管理

<hibernate-mapping>
    <query name="findRichUsers">
        FROM User u WHERE u.balance > :minBalance
    </query>
</hibernate-mapping>

// 使用
Query q = session.getNamedQuery("findRichUsers");
q.setParameter("minBalance", 10000);

原生 SQL 查詢

SQLQuery sql = session.createSQLQuery("SELECT * FROM user WHERE status = ?")
    .addEntity(User.class)
    .setInteger(0, 1);
List users = sql.list();

效能優化清單

  • 避免 FROM java.lang.Object 全表掃描
  • 使用 fetch="join" 或 LEFT JOIN FETCH 解決 N+1 問題
  • 大量資料採用 ScrollableResults / Stream 串流處理
  • 啟用二級快取(Ehcache/Infinispan)針對唯讀/少寫實體
  • 批次抓取 @BatchSize(size=20) 或 hibernate.default_batch_fetch_size

現代化演進

  • Hibernate 5.2+:CriteriaBuilder / CriteriaQuery (JPA 標準) 取代舊 Criteria API
  • Spring Data JPA:JpaSpecificationExecutor + Specification 實現型別安全動態查詢
  • QueryDSL:流暢 API、編譯時檢查、支援 JPA/SQL/MongoDB
  • Blaze-Persistence:進階 Criteria 實現、CTE、遞迴查詢

總結

HQL 適合靜態、複雜、報表查詢,可讀性高;Criteria 適合動態條件組合、通用搜尋元件。現代專案建議採用 JPA CriteriaBuilder 或 QueryDSL,兼得型別安全與表達力。理解兩者底層皆轉譯為 SQL,善用 show_sql=true、format_sql=true 分析執行計畫,是效能調優關鍵。

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