在 `
| 值 | 行為 | SQL 範例 |
|---|---|---|
true | 使用 LEFT OUTER JOIN 一次性載入關聯物件 (急切載入) | SELECT * FROM OrderLineItem o LEFT JOIN Order p ON o.OrderId=p.OrderId WHERE o.id=? |
false | 不使用外部連接,需配合 lazy=true 實現延遲載入 (兩條 SQL) | 1. SELECT * FROM OrderLineItem WHERE id=?2. SELECT * FROM Order WHERE OrderId=? |
auto (預設) | 依 hibernate.cfg.xml 全域設定決定 | - |
使用 HQL 查詢時 (如 from OrderLineItem o where o.id='id'),永遠不使用外部連接,`outer-join` 設定失效。此時需改用 fetch join。
lazy="true" (預設)lazy="false" 時,`outer-join` 行為同 many-to-oneFROM Entity e LEFT JOIN FETCH e.association
HQL 查詢會忽略映射檔中的 `outer-join` 設定。若需在特定查詢中急切載入關聯,必須顯式使用 fetch join。
// 錯誤:會產生 N+1 查詢問題
MyObject obj = session.createQuery("FROM MyObject").uniqueResult();
obj.getMySet().iterator().next(); // 觸發額外 SQL
// 正確:使用 fetch join 一次載入
MyObject obj = session.createQuery(
"FROM MyObject mo LEFT JOIN FETCH mo.mySet").uniqueResult();
obj.getMySet().iterator().next(); // 無額外 SQL
// 錯誤:不能同時 fetch 兩個集合
FROM Department d
LEFT JOIN FETCH d.employees
LEFT JOIN FETCH d.projects
// 正確:可 fetch 一個集合 + 多個單值關聯
FROM Cat cat
INNER JOIN FETCH cat.mate // many-to-one / one-to-one
LEFT JOIN FETCH cat.kittens // one-to-many (集合)
原因: 多重集合 fetch join 會產生笛卡兒積,結果集呈指數級膨脹,嚴重影響效能。
| 查詢方式 | SQL 特徵 | 記憶體中物件狀態 |
|---|---|---|
LEFT JOIN (無 fetch) | SQL 有 JOIN,但 SELECT 子句不包含關聯表欄位 | 關聯物件為 proxy/未初始化,存取時觸發額外查詢 |
LEFT JOIN FETCH | SQL 有 JOIN,SELECT 包含關聯表欄位 | 關聯物件 完全初始化,無額外查詢 |
// 僅 JOIN,不 FETCH
FROM Order o LEFT JOIN o.customer c WHERE o.id = 1
// 產生 SQL 有 JOIN,但 Order 的 customer 仍為 proxy
// JOIN FETCH
FROM Order o LEFT JOIN FETCH o.customer c WHERE o.id = 1
// Order 的 customer 完全載入
| 映射設定 | HQL 使用 fetch join | 結果 |
|---|---|---|
集合 lazy="true" | 是 | 延遲載入失效,強制急切載入 |
many-to-one 端 fetch="join" | 否/是 | 永遠急切載入 (映射層級強制) |
lazy="true",避免不必要的資料載入LEFT JOIN FETCH 精準載入所需關聯@BatchSizeINNER JOIN FETCH 效能更好LEFT JOIN FETCH 集合會導致主實體重複 (一對多)。解決:在 Java 端用 new LinkedHashSet<>(list) 去重,或改用 DISTINCT (但可能影響資料庫執行計畫)。
Hibernate 記憶體分頁時,fetch join 集合會導致記錄筆數不準。解決:分頁查詢主實體 ID,再以 ID 列表 fetch 完整物件 (兩次查詢)。
# hibernate.cfg.xml
true
true
true
觀察實際產生的 SQL,確認是否產生預期的 JOIN/FETCH 行為。