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

Hibernate HQL 查詢語言完全指南:從入門到進階 (投影、關聯、批量更新、命名查詢、分頁)

     編輯:Java 相關知識

前言

HQL (Hibernate Query Language) 是面向對象的查詢語言,編譯為 SQL 執行。掌握 HQL 能避免原生 SQL 的表結構耦合,享受實體映射、緩存、攔截器等 ORM 紅利。本文系統講解 HQL 核心語法、投影查詢、關聯抓取、批量操作、命名查詢、分頁與參數綁定最佳實踐。

一、基礎查詢語法

場景HQL說明
查詢所有實體from User類名而非表名,大小寫敏感
條件查詢from User u where u.age > 20 and u.age < 60別名 u 簡化屬性訪問
投影查詢 (標量)select u.name, u.age from User u where u.age > 20返回 List<Object[]>
投影查詢 (實體構造)select new User(u.name, u.age) from User u where u.age > 20需實體有對應構造器,返回 List<User>
聚合函數select avg(u.age) from User ucount, sum, min, max, avg
子查詢from User u where u.age > (select avg(u2.age) from User u2)WHERE/SELECT/HAVING 均可

二、關聯查詢與抓取策略

// 實體關聯:User 1:N Address
// 1. 內連接 (僅有地址的用戶)
from User u inner join fetch u.addresses
// 2. 左外連接 (所有用戶,無地址者 address 為 null)
from User u left join fetch u.addresses
// 3. 右外連接 (所有地址,無用戶者 user 為 null)
from User u right join fetch u.addresses
// 4. 完全連接
from User u full join fetch u.addresses

關鍵差異:fetch vs 無 fetch

  • fetch:HQL 返回實體對象 (List<User>),關聯集合已初始化,避免 N+1。
  • 無 fetch:返回 List<Object[]>,每行包含 [User, Address],需手動組裝。

三、批量更新與刪除 (HQL 執行更新)

// 批量更新
int updated = session.createQuery("update User set name = 'NewName' where name = 'OldName'")
                     .executeUpdate();

// 批量刪除
int deleted = session.createQuery("delete User where lastLogin < :date")
                     .setParameter("date", LocalDate.now().minusYears(1))
                     .executeUpdate();

注意:executeUpdate() 直接發 SQL,**不觸發**實體生命週期回調、不更新一級緩存、不級聯。使用後建議 session.clear() 或重新查詢。

四、參數綁定:位置參數 vs 命名參數 vs 實體屬性注入

方式語法API適用場景
位置參數where u.name = ?query.setString(0, "val")簡單 1-2 參數,**索引從 0 開始**
命名參數where u.name = :namequery.setParameter("name", "val")多參數、可讀性、重用
實體屬性注入where u.name = :namequery.setProperties(userQuery)查詢條件封裝為 POJO (UserQuery)

五、命名查詢

5.1 映射文件定義

<hibernate-mapping>
    <query name="User.byName"><![CDATA[
        from User u where u.name = :name
    ]]></query>
</hibernate-mapping>

5.2 註解定義

@NamedQuery(name = "User.byName", query = "from User u where u.name = :name")

5.3 使用

Query q = session.getNamedQuery("User.byName");
q.setParameter("name", "Alice");
List<User> list = q.list();

六、分頁查詢最佳實踐

Query q = session.createQuery("from User u order by u.id");
q.setFirstResult((pageNo - 1) * pageSize); // offset
q.setMaxResults(pageSize); // limit
List<User> page = q.list();

// 總數查詢 (可優化為子查詢或緩存)
Long total = (Long) session.createQuery("select count(*) from User").uniqueResult();

七、HQL vs SQL vs Criteria vs JPA QL

特性HQLSQLCriteria (Deprecated)JPA QL
面向對象✅❌✅ (程式化)✅ (標準)
類型安全❌❌✅❌
動態查詢構建字串拼接字串拼接✅ API字串拼接
原生函數/方言受限✅ 完全受限受限
推薦度⭐⭐⭐⭐⭐⭐ (特殊場景)⭐ (已棄用)⭐⭐⭐⭐⭐ (新專案首選)

新專案建議:優先使用 JPA QL / Spring Data JPA Repository,複雜報表/原生函數才落回 @Query(nativeQuery=true) 或 Session.createNativeQuery()。

八、常見陷阱與優化

陷阱後果解決
投影查詢無 ID 導致 saveOrUpdate 變 INSERT重複數據投影包含 ID:select new User(u.id, u.name, u.age)...
大量數據未分頁OOM必加 setFirstResult/setMaxResults
批量更新未清緩存緩存髒讀session.clear() 或 evict()
關聯未 fetch 觸發 N+1效能災難join fetch、@BatchSize、EntityGraph

九、總結

HQL 以實體類與屬性為查詢對象,編譯為優化 SQL,提供投影構造、關聯抓取、批量操作、命名查詢、參數綁定等豐富特性。掌握 HQL 核心語法與陷阱,是 Hibernate 高效開發的必修課。

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