| 組件 | 職責 | 生命週期 | 執行緒安全 |
|---|---|---|---|
| Configuration | 讀取映射與配置,建構 SessionFactory | 啟動時一次性 | 否 |
| SessionFactory | 緩存映射元數據、二級快取、連線池;生產 Session | 應用全生命週期(單例) | 是 |
| Session | 一級快取、持久化上下文、資料庫連線持有者、事務邊界 | 請求/事務級(短暫) | 否 |
Session.connection() 可取得底層 JDBC Connection,但不建議直接操作,破壞 Hibernate 狀態管理。
新建 new Entity() → [save()/persist()] → 持久態 (Session 管理)
↑ │
│ ▼
│ [evict()/close()/clear()]
│ │
└──────── [update()/saveOrUpdate()/merge()/lock()] ← 游離態
(重新關聯)
游離態亦可 → [delete()] → 從資料庫刪除 → 變瞬時態
| 方法 | 適用狀態 | 回傳值 | SQL 時機 | 備註 |
|---|---|---|---|---|
save() | 瞬時態 | ID (Serializable) | flush/commit | 立即賦予 ID(視生成策略) |
persist() | 瞬時態/持久態 | void | flush/commit | JPA 標準,不保證立即產生 ID,不可用於游離態 |
update() | 游離態 | void | flush/commit | 資料庫必須存在記錄,否則異常 |
saveOrUpdate() | 瞬時態/游離態 | void | flush/commit | 依 unsaved-value 判斷新舊 |
merge() | 瞬時態/游離態/持久態 | 持久態實例 | flush/commit | 複製狀態至受管理實例,最安全,回傳值需用於後續操作 |
delete() | 持久態/游離態 | void | flush/commit | 游離態先重新關聯再刪除 |
lock() | 游離態 | void | 無 | 僅重新關聯,不檢查變更,配合 LockMode 實現樂觀/悲觀鎖 |
replicate() | 游離態 | void | flush/commit | 強制用給定 ID 持久化,需指定 ReplicationMode,極少用 |
| 特性 | get() | load() |
|---|---|---|
| 不存在時 | 回傳 null | 拋 ObjectNotFoundException(存取時) |
| 回傳型態 | 實體實例 | Proxy 代理(未存取時不查資料庫) |
| 資料庫查詢時機 | 立即 | 首次存取非 ID 屬性時 |
| 適用場景 | 不確定是否存在 | 確定存在、只需建立關聯(如設定外鍵) |
建議:預設用 get(),確定存在且追求效能時用 load()。
clear() 清空所有,evict(entity) 移除指定實體。evict() 用於批量處理釋放記憶體。hibernate.cache.use_second_level_cache=true 並配置快取提供者。實體映射加 <cache usage="read-write"/>。query.setCacheable(true)。<!-- hibernate.cfg.xml -->
<property name="hibernate.transaction.factory_class">
org.hibernate.transaction.JDBCTransactionFactory <!-- 預設,單資料源 -->
</property>
<!-- 或 -->
<property name="hibernate.transaction.factory_class">
org.hibernate.transaction.JTATransactionFactory <!-- 多資料源/分散式事務 -->
</property>
Connection/Session,簡單輕量。HibernateTransactionManager(單資料源)或 JtaTransactionManager(多資料源),配合 @Transactional 宣告式事務,最推薦。注意:MySQL MyISAM 不支援事務,須使用 InnoDB;學習階段建議 PostgreSQL/Oracle/DB2。
| 介面 | 特點 | 適用場景 |
|---|---|---|
| HQL/JPQL | 面向物件、型別安全、支援多態、可攜帶參數 | 大多數業務查詢 |
| Criteria/JPA CriteriaBuilder | 程式化構建、類型安全、適合動態查詢 | 複雜動態條件、分頁框架 |
| Native SQL | 直接寫 SQL、資料庫特有函數、複雜報表 | 效能調優、異構查詢、存儲過程 |
DetachedCriteria 為離線查詢模板,可序列化傳遞,執行時 getExecutableCriteria(session) 綁定 Session。
lazy 屬性class lazy="true"(load() 回傳 Proxy)。lazy="true",存取時初始化。lazy="extra":size()、contains() 不初始化全集合。Hibernate.initialize(proxy/collection) 強制初始化。LazyInitializationException。Hibernate.isInitialized(obj):檢查 Proxy/集合是否已初始化。Hibernate.getClass(proxy):取得 Proxy 真實實體類別。Hibernate.unproxy(proxy):若已初始化回傳實體,否則回傳 null。// 持久化
session.save(entity); // 新增
session.update(detached); // 更新游離態
session.saveOrUpdate(entity); // 新增或更新
session.merge(detached); // 合併,回傳受管理實例
session.delete(entity); // 刪除
// 查詢
session.get(Class, id); // 立即查,可能 null
session.load(Class, id); // 延遲 Proxy,不存在拋異常
session.createQuery(hql); // HQL
session.createNativeQuery(sql); // 原生 SQL
session.createCriteria(Class); // Criteria (舊 API)
// 快取/狀態
session.flush(); // 同步至 DB
session.evict(entity); // 移出一級快取
session.clear(); // 清空一級快取
session.contains(entity); // 是否在快取中
session.refresh(entity); // 從 DB 重新載入覆蓋快取
// 事務
Transaction tx = session.beginTransaction();
tx.commit(); / tx.rollback();
// 關閉
session.close(); // 釋放連線、清快取
sessionFactory.close(); // 應用關閉時
熟練掌握 Session 生命週期、三態轉換、快取行為與事務邊界,是高效使用 Hibernate 的關鍵。