Hibernate `Session.get()` 與 `Session.load()` 均用於按 ID 獲取實體,但底層機制截然不同。本文對比立即加載與延遲加載、代理對象本質、三大異常場景(NPE、ObjectNotFoundException、LazyInitializationException)及解決方案。
| 特性 | get() | load() |
|---|---|---|
| 加載策略 | 立即加載 | 延遲加載(代理) |
| 發送 SQL 時機 | 調用時立即 | 首次訪問非 ID 屬性時 |
| 返回對象 | 真實實體 / null | 代理對象(含 ID) |
| ID 不存在 | 返回 null | 拋 ObjectNotFoundException |
| Session 關閉後訪問 | 安全(已加載) | 拋 LazyInitializationException |
| 性能 | 稍慢(必查庫) | 快(僅需 ID 時不查庫) |
User u = (User) session.get(User.class, 999L); // 不存在 System.out.println(u.getName()); // NullPointerException
解決:判空守衛 `if (u != null)` 或改用 `load()` 統一拋出可捕獲異常。
public User loadUser(Long id) {
Session s = factory.openSession();
User u = (User) s.load(User.class, id);
s.close(); // Session 關閉
return u; // 返回未初始化代理
}
// 調用方
User u = dao.loadUser(1L);
System.out.println(u.getName()); // LazyInitializationException: could not initialize proxy - no Session
兩種解決方案: