Hibernate是對JDBC的輕量級對象封裝
Hibernate本身是不具備Transaction處理功能的
Hibernate的Transaction實際上是底層的JDBC Transaction的封裝
或者是JTA Transaction的封裝
下面我們詳細的分析
Hibernate可以配置為JDBCTransaction或者是JTATransaction
這取決於你在hibernate
properties中的配置:
#hibernate
transaction
factory_class
net
sf
hibernate
transaction
JTATransactionFactory
#hibernate
transaction
factory_class
net
sf
hibernate
transaction
JDBCTransactionFactory
如果你什麼都不配置
默認情況下使用JDBCTransaction
如果你配置為
hibernate
transaction
factory_class
net
sf
hibernate
transaction
JTATransactionFactory
將使用JTATransaction
不管你准備讓Hibernate使用JDBCTransaction
還是JTATransaction
我的忠告就是什麼都不配
將讓它保持默認狀態
如下
#hibernate
transaction
factory_class
net
sf
hibernate
transaction
JTATransactionFactory
#hibernate
transaction
factory_class
net
sf
hibernate
transaction
JDBCTransactionFactory
在下面的分析中我會給出原因
一JDBC Transaction 看看使用JDBC Transaction的時候我們的代碼例子
Session session = sf
openSession();
Transaction tx = session
beginTransactioin();
session
flush();
mit();
session
close();
這是默認的情況
當你在代碼中使用Hibernate的Transaction的時候實際上就是JDBCTransaction
那麼JDBCTransaction究竟是什麼東西呢?來看看源代碼就清楚了
Hibernate
源代碼中的類
net
sf
hibernate
transaction
JDBCTransaction:
public void begin() throws HibernateException {
if (toggleAutoCommit) nnection()
setAutoCommit(false);
}
這是啟動Transaction的方法
看到 connection()
setAutoCommit(false) 了嗎?是不是很熟悉?
再來看
public void commit() throws HibernateException {
try {
if ( session
getFlushMode()!=FlushMode
NEVER ) session
flush();
try {
nnection(mit();
committed = true;
}
toggleAutoCommit();
}
這是提交方法
看到connection(mit() 了嗎?下面就不用我多說了
這個類代碼非常簡單易懂
通過閱讀使我們明白Hibernate的Transaction都在干了些什麼?我現在把用Hibernate寫的例子翻譯成JDBC
大家就一目了然了
Connection conn =
; <
session = sf
openSession();
conn
setAutoCommit(false); <
tx = session
beginTransactioin();
<
mit(); <
mit(); (對應左邊的兩句)
conn
setAutoCommit(true);
conn
close(); <
session
close();
看明白了吧
Hibernate的JDBCTransaction根本就是mit而已
根本毫無神秘可言
只不過在Hibernate中
Session打開的時候
就會自動conn
setAutoCommit(false)
不像一般的JDBC
默認都是true
所以你最後不寫commit也沒有關系
由於Hibernate已經把AutoCommit給關掉了
所以用Hibernate的時候
你在程序中不寫Transaction的話
數據庫根本就沒有反應
二JTATransaction 如果你在EJB中使用Hibernate
或者准備用JTA來管理跨Session的長事務
那麼就需要使用JTATransaction
先看一個例子
javax
transaction
UserTransaction tx = new
InitialContext()
lookup(
javax
transaction
UserTransaction
);
Session s
= sf
openSession();
s
flush();
s
close();
Session s
= sf
openSession();
s
flush();
s
close();
mit();
這是標准的使用JTA的代碼片斷
Transaction是跨Session的
它的生命周期比Session要長
如果你在EJB中使用Hibernate
那麼是最簡單不過的了
你什麼Transaction代碼統統都不要寫了
直接在EJB的部署描述符上配置某某方法是否使用事務就可以了
現在我們來分析一下JTATransaction的源代碼
net
sf
hibernate
transaction
JTATransaction:
public void begin(InitialContext context
ut = (UserTransaction) context
lookup(utName);
看清楚了嗎? 和我上面寫的代碼 tx = new Initial Context?()
lookup(
javax
transaction
UserTransaction
); 是不是完全一樣?
public void commit()
if (newTransaction) mit();
JTATransaction的控制稍微復雜
不過仍然可以很清楚的看出來Hibernate是如何封裝JTA的Transaction代碼的
但是你現在是否看到了什麼問題? 仔細想一下
Hibernate Transaction是從Session中獲得的
tx = session
beginTransaction()
最後要先提交tx
然後再session
close
這完全符合JDBC的Transaction的操作順序
但是這個順序是和JTA的Transactioin操作順序徹底矛盾的!!! JTA是先啟動Transaction
然後啟動Session
關閉Session
最後提交Transaction
因此當你使用JTA的Transaction的時候
那麼就千萬不要使用Hibernate的Transaction
而是應該像我上面的JTA的代碼片斷那樣使用才行
總結 在JDBC上使用Hibernate 必須寫上Hibernate Transaction代碼
否則數據庫沒有反應
此時Hibernate的Transaction就是mit而已
在JTA上使用Hibernate 寫JTA的Transaction代碼
不要寫Hibernate的Transaction代碼
否則程序會報錯
在EJB上使用Hibernate 什麼Transactioin代碼都不要寫
在EJB的部署描述符裡面配置
|
CMT(Container Managed Transaction)
|
|
BMT(Bean Managed Transaction)
|
|
JDBC Transaction
|
|
JTA Transaction
From:http://tw.wingwit.com/Article/program/Java/ky/201311/28725.html