首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> JSP 程式設計 >> 關於JSP

Hibernate 核心 API 深度解析:Session、事務、快取、查詢與鎖機制全景圖

     編輯:關於JSP

核心架構三層:Configuration → SessionFactory → Session

組件職責生命週期執行緒安全
Configuration讀取映射與配置,建構 SessionFactory啟動時一次性否
SessionFactory緩存映射元數據、二級快取、連線池;生產 Session應用全生命週期(單例)是
Session一級快取、持久化上下文、資料庫連線持有者、事務邊界請求/事務級(短暫)否

Session.connection() 可取得底層 JDBC Connection,但不建議直接操作,破壞 Hibernate 狀態管理。

實體三大狀態與轉換圖譜

新建 new Entity() → [save()/persist()] → 持久態 (Session 管理)
       ↑                                      │
       │                                      ▼
       │                              [evict()/close()/clear()]
       │                                      │
       └──────── [update()/saveOrUpdate()/merge()/lock()] ← 游離態
                     (重新關聯)
       游離態亦可 → [delete()] → 從資料庫刪除 → 變瞬時態
  • 瞬時態:無 ID,無 Session 關聯,資料庫無記錄。
  • 持久態:有 ID,關聯 Session,納入一級快取,享有髒檢查、延遲載入、級聯操作。
  • 游離態:曾持久化,Session 結束/脫離,保留 ID 與版本,可重新關聯。

Session 核心持久化方法對比

方法適用狀態回傳值SQL 時機備註
save()瞬時態ID (Serializable)flush/commit立即賦予 ID(視生成策略)
persist()瞬時態/持久態voidflush/commitJPA 標準,不保證立即產生 ID,不可用於游離態
update()游離態voidflush/commit資料庫必須存在記錄,否則異常
saveOrUpdate()瞬時態/游離態voidflush/commit依 unsaved-value 判斷新舊
merge()瞬時態/游離態/持久態持久態實例flush/commit複製狀態至受管理實例,最安全,回傳值需用於後續操作
delete()持久態/游離態voidflush/commit游離態先重新關聯再刪除
lock()游離態void無僅重新關聯,不檢查變更,配合 LockMode 實現樂觀/悲觀鎖
replicate()游離態voidflush/commit強制用給定 ID 持久化,需指定 ReplicationMode,極少用

查詢方法:get() vs load()

特性get()load()
不存在時回傳 null拋 ObjectNotFoundException(存取時)
回傳型態實體實例Proxy 代理(未存取時不查資料庫)
資料庫查詢時機立即首次存取非 ID 屬性時
適用場景不確定是否存在確定存在、只需建立關聯(如設定外鍵)

建議:預設用 get(),確定存在且追求效能時用 load()。

快取管理:一級快取與清理

  • 一級快取:Session 級,不可關閉,存放持久態實體。clear() 清空所有,evict(entity) 移除指定實體。
  • flush():強制同步快取變更至資料庫(執行 INSERT/UPDATE/DELETE)。常搭配 evict() 用於批量處理釋放記憶體。
  • 二級快取:SessionFactory 級,跨 Session 共用。需啟用 hibernate.cache.use_second_level_cache=true 並配置快取提供者。實體映射加 <cache usage="read-write"/>。
  • 查詢快取:緩存查詢結果集(ID 列表),配合二級快取使用。query.setCacheable(true)。

事務管理:JDBC vs JTA

<!-- 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>
  • JDBC 事務:綁定單一 Connection/Session,簡單輕量。
  • JTA 事務:跨多個資料源/Session,通常由應用伺服器管理。不可混用 JDBC 與 JTA 事務 API。
  • Spring 整合:使用 HibernateTransactionManager(單資料源)或 JtaTransactionManager(多資料源),配合 @Transactional 宣告式事務,最推薦。

注意:MySQL MyISAM 不支援事務,須使用 InnoDB;學習階段建議 PostgreSQL/Oracle/DB2。

查詢介面:HQL、Criteria、Native SQL

介面特點適用場景
HQL/JPQL面向物件、型別安全、支援多態、可攜帶參數大多數業務查詢
Criteria/JPA CriteriaBuilder程式化構建、類型安全、適合動態查詢複雜動態條件、分頁框架
Native SQL直接寫 SQL、資料庫特有函數、複雜報表效能調優、異構查詢、存儲過程

DetachedCriteria 為離線查詢模板,可序列化傳遞,執行時 getExecutableCriteria(session) 綁定 Session。

延遲載入與 lazy 屬性

  • Hibernate 3+ 預設 class lazy="true"(load() 回傳 Proxy)。
  • 集合預設 lazy="true",存取時初始化。
  • 層級載入 lazy="extra":size()、contains() 不初始化全集合。
  • Hibernate.initialize(proxy/collection) 強制初始化。
  • 關閉 Session 前必須初始化所需關聯,否則拋 LazyInitializationException。

常用工具類方法

  • Hibernate.isInitialized(obj):檢查 Proxy/集合是否已初始化。
  • Hibernate.getClass(proxy):取得 Proxy 真實實體類別。
  • Hibernate.unproxy(proxy):若已初始化回傳實體,否則回傳 null。

總結:核心 API 速查卡

// 持久化
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 的關鍵。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved