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

Hibernate 查詢方式完整總結:從基礎到進階

     編輯:關於JSP

Hibernate 核心查詢 API 全景指南

Hibernate 提供多層次查詢機制,滿足從簡單主鍵查詢到複雜報表分析的各類需求。本文系統整理 7 種查詢方式,附帶代碼範例、適用場景與效能建議。

1. 基礎主鍵查詢:get() vs load()

// 立即查詢,無資料返回 null
User user = session.get(User.class, 1L);

// 延遲載入 (Proxy),無資料拋出 ObjectNotFoundException
User user = session.load(User.class, 1L);
特性get()load()
資料庫存取時機立即首次存取屬性時 (延遲)
無資料行為返回 null拋出異常
返回型別實體物件Proxy 代理物件
批次載入支援不支援支援 (配合 batch-size)
適用場景不確定資料是否存在確定存在、建立關聯不需即時查詢

2. HQL (Hibernate Query Language)

面向物件的查詢語言,類 SQL 但操作實體與屬性。

// 位置參數
String hql = "FROM Order o WHERE o.id = ?";
Order order = (Order) session.createQuery(hql)
    .setParameter(0, orderId)
    .uniqueResult();

// 命名參數 (推薦:可讀性高、防注入)
Query query = session.createQuery("FROM User u WHERE u.name = :name");
query.setString("name", "John");

// IN 子句參數列表
Query query = session.createQuery("FROM Product p WHERE p.category IN (:cats)");
query.setParameterList("cats", categoryList);

// 分頁查詢
Query query = session.createQuery("FROM Article a ORDER BY a.createTime DESC");
query.setFirstResult(20);  // 跳過前 20 筆 (第 3 頁,每頁 10 筆)
query.setMaxResults(10);
List<Article> list = query.list();

3. Criteria API (類型安全、程式化構建)

適合動態查詢條件 (如多條件搜尋表單)。

Criteria criteria = session.createCriteria(Cat.class);

// 條件組合
criteria.add(Restrictions.like("name", "Fritz%"));
criteria.add(Restrictions.or(
    Restrictions.eq("age", 0),
    Restrictions.isNull("age")
));

// 排序
criteria.addOrder(Order.asc("name"));
criteria.addOrder(Order.desc("age"));

// 分頁
criteria.setFirstResult(0);
criteria.setMaxResults(20);

List<Cat> cats = criteria.list();

// 投影查詢 (僅選取特定欄位)
criteria.setProjection(Projections.projectionList()
    .add(Projections.property("id"), "id")
    .add(Projections.property("name"), "name")
);
List<Object[]> rows = criteria.list();

4. Native SQL (原生 SQL 查詢)

處理資料庫特有語法、複雜報表、存儲過程、HQL 無法表達的查詢。

// 遞迴查詢 (Oracle CONNECT BY)
String sql = "SELECT t.*, LEVEL FROM tree t " +
             "START WITH t.parent_id = 0 " +
             "CONNECT BY PRIOR t.id = t.parent_id";

List<Object[]> result = session.createSQLQuery(sql)
    .addEntity("t", Tree.class)      // 映射實體
    .addScalar("level", Hibernate.INTEGER) // 映射額外欄位
    .list();

// 純標量查詢 (非實體)
List<Object[]> summary = session.createSQLQuery(
    "SELECT COUNT(*), SUM(amount) FROM orders WHERE created > ?"
).addScalar("cnt", Hibernate.LONG)
 .addScalar("sum", Hibernate.BIG_DECIMAL)
 .setParameter(0, startDate)
 .list();

5. Named Queries (命名查詢)

在映射檔或註解中預定義,編譯期驗證、集中管理、效能優化 (預編譯)。

// 映射檔定義
<query name="User.findByEmail">
    <![CDATA[ FROM User u WHERE u.email = :email ]]>
</query>

// 程式碼呼叫
Query query = session.getNamedQuery("User.findByEmail");
query.setString("email", "test@example.com");
User user = (User) query.uniqueResult();

6. Filter (過濾器)

全域、可選啟用的條件片段,常用於軟刪除、多租戶、資料權限。

// 映射檔定義
<filter name="activeFilter" condition=":isActive = 1"/>
<filter-def name="activeFilter">
    <filter-param name="isActive" type="boolean"/>
</filter-def>

// 實體類別啟用
@Filter(name = "activeFilter", condition = "is_active = 1")
@Entity
public class Article { ... }

// 啟用/停用
session.enableFilter("activeFilter").setParameter("isActive", true);
List<Article> list = session.createQuery("FROM Article").list(); // 自動加 WHERE is_active=1
session.disableFilter("activeFilter");

7. DetachedCriteria (離線查詢)

無 Session 環境下構建查詢,稍後在任意 Session 執行。適合 Web 層構建查詢、Service 層執行。

// Web 層構建 (無 Session)
DetachedCriteria criteria = DetachedCriteria.forClass(Order.class);
criteria.add(Restrictions.ge("amount", 1000));
criteria.addOrder(Order.desc("createTime"));

// Service 層執行 (有 Session)
List<Order> orders = criteria.getExecutableCriteria(session).list();

查詢方式選擇決策樹

場景推薦方式理由
主鍵查詢單一實體get() / load()最簡潔、一級快取支援
固定條件業務查詢Named Query (HQL)預編譯、集中維護、可讀性好
動態多條件搜尋Criteria / JPA CriteriaBuilder類型安全、程式化組合條件
複雜報表/資料庫特有語法Native SQL發揮資料庫威力、避免 HQL 限制
跨層傳遞查詢條件DetachedCriteria分離構建與執行
全域橫切關注點 (軟刪除/租戶)Filter透明攔截、零侵入業務代碼

效能優化關鍵提醒

  • ✅ 善用 一級快取 (Session 級) 避免重複查詢同一實體
  • ✅ 開啟 二級快取 (Ehcache/Infinispan) 減少資料庫訪問
  • ✅ 使用 批次抓取 (`@BatchSize`, `hibernate.default_batch_fetch_size`) 解決 N+1 問題
  • ✅ 投影查詢 (Projection) 僅選取需要欄位,減少網路/記憶體開銷
  • ✅ 分頁查詢 必加 ORDER BY,確保結果穩定
  • ⚠️ 避免在循環中查詢,改用 `IN` 或批次載入
  • ⚠️ Native SQL 失去資料庫可攜性,謹慎使用

Hibernate 5.2+ / JPA 2.1 推薦使用標準 CriteriaBuilder API** (型別安全、功能對等),原生 Criteria 進入維護模式。新專案請優先採用 JPA 標準介面。

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