Hibernate 本質上是對 JDBC 的輕量級物件封裝,其 Transaction 功能並非自帶,而是對底層 JDBC Transaction 或 JTA Transaction 的封裝。透過 hibernate.transaction.factory_class 配置切換:
net.sf.hibernate.transaction.JDBCTransactionFactory(預設)net.sf.hibernate.transaction.JTATransactionFactory核心建議:除非在 EJB 環境或需跨 Session 長事務,否則保持預設 JDBCTransaction,避免不必要的複雜度。
Session session = sf.openSession();
Transaction tx = session.beginTransaction();
// 業務操作...
session.flush();
tx.commit();
session.close();
JDBCTransaction.begin() 核心調用:session.connection().setAutoCommit(false)
JDBCTransaction.commit() 核心調用:session.connection().commit() 並恢復 AutoCommit
| Hibernate 代碼 | 等價 JDBC 代碼 |
|---|---|
session = sf.openSession() | Connection conn = ... |
tx = session.beginTransaction() | conn.setAutoCommit(false) |
tx.commit() | conn.commit(); conn.setAutoCommit(true) |
session.close() | conn.close() |
關鍵洞見: Hibernate 開啟 Session 即自動關閉 AutoCommit,若不顯式開啟 Transaction,資料庫將無任何反應。JDBCTransaction 純屬 Connection.commit() 的薄封裝,無任何神秘性。
UserTransaction tx = new InitialContext().lookup("javax.transaction.UserTransaction");
Session s1 = sf.openSession(); ... s1.flush(); s1.close();
Session s2 = sf.openSession(); ... s2.flush(); s2.close();
tx.commit();
特點:Transaction 生命週期長於 Session,跨多個 Session。
JTATransaction.begin() 核心:ut = (UserTransaction) context.lookup(utName)
JTATransaction.commit() 核心:if (newTransaction) ut.commit()
JDBC 事務順序: 啟動 Transaction → 操作 Session → 提交 Transaction → 關閉 Session
JTA 事務順序: 啟動 Transaction → 啟動 Session → 關閉 Session → 提交 Transaction
⚠️ 嚴重警告: 使用 JTA 時絕不能使用 session.beginTransaction(),否則順序衝突導致程式報錯。必須直接操作 UserTransaction,像標準 JTA 代碼那樣獨立管理事務邊界。
Connection.commit()。理解 Hibernate 事務的封裝本質,認清 JDBC 與 JTA 操作順序的根本差異,是避免事務管理災難的關鍵。根據部署環境選擇正確策略,才能發揮 Hibernate 輕量級封裝的真正價值。