Hibernate 檢索策略直接決定 SQL 生成效率與記憶體佔用。本文系統梳理類級、關聯級(集合/單端)三大維度的檢索模式,提供配置矩陣與選型建議。
| 策略 | 配置 | 適用方法 | 特點 |
|---|---|---|---|
| 立即檢索 | <class lazy="false"> | get/load/query | 默認策略,無代理,查詢即加載完整對象 |
| 延遲檢索 | <class lazy="true"> | 僅 load() | 返回代理對象,首次訪問非 ID 屬性時觸發 SQL |
注意:get()、query() 無視 lazy 屬性強制立即加載。load() 不存在時拋異常,生產慎用。
通過 <set> 的 lazy、outer-join 組合控制:
| 策略 | lazy | outer-join | SQL 特徵 | 適用場景 |
|---|---|---|---|---|
| 立即檢索 | false | false | 兩條 SQL:主表 + 集合表 | 集合較小、高頻訪問 |
| 延遲檢索 | true | false | 首次訪問集合發 SQL | 默認推薦,按需加載 |
| 迫切左外連接 | false | true | 單條 LEFT JOIN SQL | 集合必用、僅限 id 查詢 |
限制:全局僅允許一個集合配置 outer-join="true";query 列表查詢無視此設置退回立即檢索。
在 <set batch-size="10"> 可將 N 次集合查詢合併為 IN 子句,大幅減少數據庫往返。
通過 <many-to-one> 的 outer-join 與關聯 <class> 的 lazy 聯動:
| outer-join | class.lazy | 策略 | 說明 |
|---|---|---|---|
| auto (默認) | true | 延遲檢索 | 返回代理,訪問時查詢 |
| auto | false | 迫切左外連接 | JOIN 主表查詢 |
| true | 任意 | 迫切左外連接 | 強制 JOIN |
| false | true | 延遲檢索 | 代理模式 |
| false | false | 立即檢索 | 獨立 SELECT |
outer-join="auto", lazy="true" 平衡性能與靈活性outer-join="true" 導致超大 JOIN,受 hibernate.max_fetch_depth 限制lazy="true" 避免無意外連接<set lazy="extra"> 智能優化:
size()、contains()、isEmpty() 觸發 SELECT COUNT(*) 而非加載全集合配置文件靜態,業務動態。HQL/Criteria 可覆蓋:
// HQL
from Order o left join fetch o.items where o.id = ?
// Criteria
criteria.setFetchMode("items", FetchMode.JOIN);
開啟 hibernate.show_sql=true 觀察實際 SQL,結合 format_sql、use_sql_comments 定位性能瓶頸。
單端優先 lazy,集合默認 lazy;
必用才 JOIN,大集合用 extra;
批量加 batch,動態靠 HQL;
SQL 要看清,調優不發愁。