Hibernate 兩大維度策略:
<class> 的 lazy 屬性控制<set>) 與單端關聯 (<many-to-one>/<one-to-one>) 分別配置| 策略 | 配置 | 適用方法 | 行為 | |
|---|---|---|---|---|
| 立即檢索 | lazy="false" (默認) | get/load/query | 立即執行 SELECT 加載對象 | |
| 延遲檢索 | lazy="true" | 僅 load() | 返回代理,首次訪問非ID屬性觸發加載 |
| 策略 | lazy | outer-join | SQL特點 | 適用查詢 |
|---|---|---|---|---|
| 立即檢索 | false | false | 兩條 SQL (主表+集合) | 所有 |
| 延遲檢索 | true | false | 按需加載集合 | 所有 (推薦默認) |
| 迫切左外連接 | false | true | 單條 LEFT JOIN SQL | 僅 id 查詢 (load/get),query 無效 |
限制:整個 SessionFactory 只能一個集合配 outer-join="true",受 hibernate.max_fetch_depth 控制外連深度。
<many-to-one> 的 outer-join + 對端 <class> 的 lazy 組合:
| outer-join | 對端 lazy | 策略 |
|---|---|---|
| auto (默認) | true | 延遲檢索 (代理) |
| auto | false | 迫切左外連接 |
| true | 任意 | 迫切左外連接 |
| false | true | 延遲檢索 |
| false | false | 立即檢索 (兩條 SQL) |
默認 auto+false 觸發左外連接,可能產生多表連接性能問題,建議顯式配置 outer-join="false" + lazy="true" 為延遲。
為緩解 N+1 問題,集合/單端關聯可配 batch-size="N":
// Criteria API
Criteria criteria = session.createCriteria(Order.class);
criteria.setFetchMode("items", FetchMode.JOIN); // 強制左外連接
criteria.setFetchMode("customer", FetchMode.SELECT); // 強制立即/延遲
// HQL
Query q = session.createQuery("from Order o left join fetch o.items");
配置 hibernate.show_sql=true 觀察實際 SQL,驗證策略生效、檢測 N+1、優化連接深度。
@BatchSize、或不映射集合改用查詢出處:https://lavasoft.blog.51cto.com/62575/222076