最近,用各種算是流行的方法寫了些Hibernate的例子(基于測試)。上次打算寫兩篇文章。① Hibernate 常用工具的配置和使用。② Hibernate 比較簡單的,基于單表操作的例子。寫了80%吧。越想越感覺意義不大。現(xiàn)在網(wǎng)上很多這方面的文章。我自己也沒有理由,自私的所謂備份。占用Blogjava的硬盤空間。就成了后來的 “冰 凍 閑 聊”
上個星期五,因為公司停電。所以休息了三天。一年前,這個數(shù)字可能會感覺太短。但是現(xiàn)在卻是突然覺得連續(xù)三天不上班。不知道該干什么好。
難道是對這種“月光”族的生活上癮拉?… 這樣的話題,等以后想明白了再說吧!~
接著說這個周末吧!因為無聊,翻翻,去年用過的一些散亂的筆記。越看越搞笑,字跡潦草,還好基本上是一些技術(shù)痕跡。找不到從前那些“少年不知愁滋味”的感覺。
因為我一直不是很喜歡看書。現(xiàn)在的書,寫得好的不多,但是價錢蠻貴的。所以,有時候就會把一些疑惑的問題寫在一張紙上。然后去網(wǎng)上先收集一些資料,再閱讀總結(jié)。
這里,我發(fā)現(xiàn)了一條有趣的問題。
打開hibernate.cfg.xml看看具體的JDBCTransaction 和 JTATransaction 配置:

2

3

4

5

6

7

8

9

10

可能你還會問:“除了這兩種還有其他的選擇嗎?到底選擇那一種好呢?在一個應(yīng)用中能混合使用嗎?”等等問題
分析和解答:
第一個問題
可以選擇其他的事務(wù)管理方式。不過都是JTA的不同實現(xiàn)版本。這個目錄下面有羅列出來hibernate-3.0\src\org\hibernate\transaction。比如:

2

3

4

第二個問題
概念事務(wù):事務(wù)就是能以整體的原子操作形式完成的一系列操作。
是不是感覺有些饒口?簡單的說,事務(wù) 就是一個邏輯工作單元。其中包括一系列的操作。至于事務(wù)為什么會產(chǎn)生?有什么基本特性?等等。。這些問題今天不就詳細的羅列了。網(wǎng)絡(luò)上有寫得很好的文章。
Hibernate 是JDBC的輕量級封裝。他本身并不具備事物管理的能力。事務(wù)的管理和調(diào)度將委托給JDBC或者JTA去做。
先說,他默認的事務(wù)處理機制[ JDBC Transaction ],這的確是最簡單的處理方式,因為Hibernate只是對JDBC事物做了一層簡單
的封裝。JDBC事務(wù)由Connection管理。事務(wù)周期局限于Connection的生命周期之內(nèi)。在Hibernate中這種事務(wù)周期也就局限于一個Session之內(nèi)。做個比較吧!
Connection conn = … ; <--- session = sf.openSession();// 初始化數(shù)據(jù)庫連接,
和setAutoCommit= false;
conn.setAutoCommit(false); <--- tx = session.beginTransactioin(); 會再次確認setAutoCommit是否是false
調(diào)用業(yè)務(wù)方法 <--- 調(diào)用業(yè)務(wù)方法
conn.commit(); <--- tx.commit(); (對應(yīng)左邊的兩句) 這里很關(guān)鍵,關(guān)掉自動commit。自己就必須做commit。否則數(shù)據(jù)是不會被持久到數(shù)據(jù)庫
conn.setAutoCommit(true);
conn.close(); <--- session.close();
簡單吧!如果你對JDBC有了解,看到這里可能會壞笑,NND就這么簡單,我也會封裝…有興趣的話可以直接去看看具體的源代碼。
JTA 提供了跨Session的事務(wù)管理能力。JTA的事務(wù)是要容器支持的,即JTS,用來分布式的要求比較多一些,比如像銀行這種大系統(tǒng),處理多個事務(wù)源的這些的。
JTA事務(wù)管理則是由JTA容器實現(xiàn)。事務(wù)的生命周期完全由容器來維護。容器中可以有很多Connection。按照執(zhí)行的順序,因該是串聯(lián)的一條JDBC Connection事務(wù)鏈。所以JTA的事務(wù)周期可以跨多個JDBC Connection的生命周期。在Hibernate中這種事務(wù)周期也就可以跨越多個Session。
所以。JTA事務(wù)的Connection不能對事務(wù)管理進行干涉。意思就是,假如使用了JTA就不應(yīng)該再重復(fù)調(diào)用Hibernate的Transaction功能。這里涉及到一種事務(wù)模型(嵌套式事務(wù)模型)的問題。這里也不詳細的介紹具體的幾種事務(wù)模型了。在EJB2.0規(guī)范里面也不支持這種事務(wù)處理模型。
例如 :

2

3

4

5

6

7

8

9

那么下面這段代碼

2

3

就不能在class A 和 class B 中出現(xiàn)。
原因:session.beginTransaction()也同樣執(zhí)行了InitialContext.lookup方法來獲UserTransaction的實例,tx.commit()也同樣調(diào)用了UserTransaction.commit().這樣做就會形成嵌套式的事務(wù)。在Hibernate里面是不被允許的。會導(dǎo)致運行期錯誤。
談到這里,不難看出,他們都有著自己鮮明的特點和基本的聯(lián)系?;氐介_頭的問題,在實際項目中該選用誰好呢?
這就需要分情況而定了。
1) 如果項目有用到Sessionbean.可能你會疑問?這時候由誰來管理事務(wù)呢?
答案:用SessionBean來管理。使用JTA會很方便。因為你完全沒有必要去理會Transaction。直接在SessionBean的部署描述符里面聲明事務(wù)就行了。
2) 自己實現(xiàn)一個Service類,來統(tǒng)一調(diào)用持久層的方法。這樣也能做到前后臺的松耦合。但是這時候你對session和Transaction的處理就需要小心了。如果系統(tǒng)考慮分布式就使用JTA否則就JDBC足夷。但還是有必要考慮系統(tǒng)的升級,變遷什么的。對session和Transaction的處理,最好不要放在DAO里面做。單獨實現(xiàn)一個模板類來統(tǒng)一做。具體的原因和做法,以后有時間再寫出來。
第三個問題
由于SessionFactory是線程安全的,他的創(chuàng)建過程非常復(fù)雜,代價極其昂貴。一個應(yīng)用中最好只有一個SessionFactory。事務(wù)管理類型的選擇是在SessionFactory的屬性里面配置的。這里只能選擇一種事務(wù)管理方式。
當然,你可以說還有特殊的情況,假如,這個應(yīng)用需要連接到兩臺數(shù)據(jù)庫服務(wù)器,就必須為他創(chuàng)建另一個SessionFactory。那么就可以選用另一種事務(wù)管理方式。表面上看這種情況是可以的。居于兩種事務(wù)的性能考慮?;旌陀玫囊饬x不是很大。假設(shè)這樣用+面對考慮不周全的DAO,也違背了設(shè)計原則,想想,這樣的話,因為數(shù)據(jù)庫的變動,還得回去修改DAO的代碼嗎?(可能會產(chǎn)生嵌套問題)
所以關(guān)于這個問題的結(jié)論就是:
在一個SessionFactory中只能選用一種事務(wù)管理
面對多個SessionFactory的時候,可以混合用,但是不推薦
2005-11-28 CTU OFFICE GOINGMM