事務必須服從ISO/IEC所制定的ACID原則。ACID是原子性(atomicity)、一致性(consistency)、隔離性(isolation)和持久性(durability)的縮寫。事務的原子性表示事務執行過程當中的任何失敗都將致使事務所作的任何修改失效。一致性表示當事務執行失敗時,全部被該事務影響的數據都應該恢復到事務執行前的狀態。隔離性表示在事務執行過程當中對數據的修改,在事務提交以前對其餘事務不可見。持久性表示已提交的數據在事務執行失敗時,數據的狀態都應該正確。html
通俗的理解,事務是一組原子操做單元,從數據庫角度說,就是一組SQL指令,要麼所有執行成功,若由於某個緣由其中一條指令執行有錯誤,則撤銷先前執行過的全部指令。更簡答的說就是:要麼所有執行成功,要麼撤銷不執行。java
既然事務的概念從數據庫而來,那Java事務是什麼?之間有什麼聯繫? mysql
實際上,一個Java應用系統,若是要操做數據庫,則經過JDBC來實現的。增長、修改、刪除都是經過相應方法間接來實現的,事務的控制也相應轉移到Java程序代碼中。所以,數據庫操做的事務習慣上就稱爲Java事務。程序員
事務是爲解決數據安全操做提出的,事務控制實際上就是控制數據的安全訪問。具一個簡單例子:好比銀行轉賬業務,帳戶A要將本身帳戶上的1000元轉到B帳戶下面,A帳戶餘額首先要減去1000元,而後B帳戶要增長1000元。假如在中間網絡出現了問題,A帳戶減去1000元已經結束,B由於網絡中斷而操做失敗,那麼整個業務失敗,必須作出控制,要求A帳戶轉賬業務撤銷。這才能保證業務的正確性,完成這個操走就須要事務,將A帳戶資金減小和B帳戶資金增長方到一個事務裏面,要麼所有執行成功,要麼操做所有撤銷,這樣就保持了數據的安全性。web
Java事務的類型有三種:JDBC事務、JTA(JavaTransaction API)事務、容器事務。sql
一、JDBC事務數據庫
JDBC 事務是用 Connection 對象控制的。JDBCConnection 接口( java.sql.Connection )提供了兩種事務模式:自動提交和手工提交。 java.sql.Connection 提供瞭如下控制事務的方法:編程
public void setAutoCommit(boolean)緩存
public boolean getAutoCommit()安全
public void commit()
public void rollback()
使用 JDBC 事務界定時,您能夠將多個 SQL 語句結合到一個事務中。JDBC 事務的一個缺點是事務的範圍侷限於一個數據庫鏈接。一個 JDBC 事務不能跨越多個數據庫
二、JTA(Java Transaction API)事務
JTA是一種高層的,與實現無關的,與協議無關的API,應用程序和應用服務器可使用JTA來訪問事務。
JTA(Java Transaction API)容許應用程序執行分佈式事務處理:在兩個或多個網絡計算機資源上訪問而且更新數據,這些數據能夠分佈在多個數據庫上,JDBC驅動程序的JTA支持極大地加強了數據訪問能力。
若是計劃用 JTA 界定事務,那麼就須要有一個實現javax.sql.XADataSource 、 javax.sql.XAConnection 和 javax.sql.XAResource 接口的 JDBC 驅動程序。一個實現了這些接口的驅動程序將能夠參與 JTA 事務。一個 XADataSource 對象就是一個 XAConnection 對象的工廠。 XAConnection是參與 JTA 事務的 JDBC 鏈接。
您將須要用應用服務器的管理工具設置 XADataSource 。從應用服務器和 JDBC 驅動程序的文檔中能夠了解到相關的指導。
J2EE 應用程序用 JNDI 查詢數據源。一旦應用程序找到了數據源對象,它就調用 javax.sql.DataSource.getConnection() 以得到到數據庫的鏈接。
XA 鏈接與非 XA 鏈接不一樣。必定要記住 XA 鏈接參與了 JTA 事務。這意味着 XA 鏈接不支持 JDBC 的自動提交功能。同時,應用程序必定不要對 XA 鏈接調用 java.sql.Connection.commit() 或者java.sql.Connection.rollback() 。相反,應用程序應該使用UserTransaction.begin()、 UserTransaction.commit() 和 serTransaction.rollback() 。
JTA(Java Transaction API)容許應用程序執行分佈式事務處理--在兩個或多個網絡計算機資源上訪問而且更新數據。JDBC驅動程序的JTA支持極大地加強了數據訪問能力。
本文的目的是要提供一個關於的Java事務處理API(JTA)的高級的概述,以及與分佈式事務相關的內容。一個事務處理定義了一個工做邏輯單元,要麼完全成功要麼不產生任何結果。 一個分佈式事務處理只是一個在兩個或更多網絡資源上訪問和更新數據的事務處理,所以它在那些資源之間必然是等價的。在本文中,咱們主要關心的是如何處理關係數據庫系統。
咱們要討論的分佈式事務處理(DTP)模型中包含的組件是:
應用程序
應用程序服務器
事務管理程序
資源適配器
資源管理程序
在之後的內容中,咱們將描述這些組件以及它們與JTA和數據庫訪問的關係。
最好把分佈式事務處理中包含的組件看做是獨立的過程,而不是考慮它們在一個特定的電腦中的位置。這些組件中的一些能夠保存在單機中,或者也可在好幾臺機器之間分佈。
最簡單的例子:用於本地數據庫事務處理的應用程序
關係數據庫訪問的最簡單的形式僅僅包括應用程序、資源管理程序和資源適配器。應用程序只不過是發送請求到數據庫而且從數據庫中獲取數據的最終用戶訪問點
咱們討論的資源管理程序是一個關係數據庫管理系統(RDBMS),好比Oracle或者SQL Server。全部的實際數據庫管理都是由這個組件處理的。
資源適配器是外部空間之間的通訊管道組件,或者是請求翻譯器,在單個的本地事務處理中,這是一個JDBC驅動程序。應用程序發送一個用於JDBC驅動程序數據的請求,而後翻譯這個請求並把它經過網絡發送到數據庫中。 數據庫把數據發送回驅動程序,而後把翻譯的結果發送迴應用程序。
到目前爲止,咱們說明了單個的本地事務處理,而且描述了分佈式事務處理模型的五個組件中的四個。第五個組件,事務管理程序只有當事務將要被分配的時候纔會開始被考慮。
分佈式事務處理和事務管理程序
像咱們前面所提到的,一個分佈式事務處理是一個在兩個或更多網絡資源上訪問和更新數據的事務處理。
這些資源能夠由好幾個位於一個單獨服務器上的不一樣的關係型數據庫管理系統組成,好比說Oracle、SQL Server和Sybase;它們也能夠包含存在於若干不一樣的服務器上的同一種數據庫的若干個實例。在任何狀況下,一個分佈式事務處理包括各類的資源管理程序之間的協同做用。這個協同做用是事務管理程序。
事務管理程序負責做出要麼提交(commit)要麼退回(rollback)任何分佈式事務處理的決定。一個提交決定應該致使一個成功的事務處理;而退回操做則是保持數據庫中的數據不變。 JTA指定一個分佈式事務處理中的事務管理程序和另外一個組件之間的標準Java接口:應用程序,應用程序服務器和資源管理程序。
JTA的三個接口部分:
一、UserTransaction,javax.transaction.UserTransaction接口提供可以編程地控制事務處理範圍的應用程序。 javax.transaction.UserTransaction方法開啓一個全局事務而且使用調用線程與事務處理關聯。
二、Transaction Manager,javax.transaction.TransactionManager接口容許應用程序服務器來控制表明正在管理的應用程序的事務範圍。
三、XAResource,javax.transaction.xa.XAResource接口是一個基於X/OpenCAE Specification的行業標準XA接口的Java映射。
注意,一個限制性環節是經過JDBC驅動程序的XAResource接口的支持。JDBC驅動程序必須支持兩個正常的JDBC交互做用:應用程序和/或應用程序服務器,並且以及JTA的XAResource部分。
編寫應用程序水平代碼的開發者不會關心分佈式事務處理管理的細節。 這是分佈式事務處理基本結構的工做:應用程序服務器、事務管理程序和JDBC驅動程序。應用程序代碼中惟一的須要注意的就是當鏈接處於一個分佈式事務範圍內的時候,不該該調用一個會影響事務邊界的方法。特別的是,一個應用程序不該該調用Connection方法commit、rollback和setAutoCommit(true),由於它們將破壞分佈式事務的基本結構管理。
分佈式事務處理
事務管理程序是分佈式事務基本結構的基本組件;然而JDBC驅動程序和應用程序服務器組件應該具有下面的特徵:
驅動程序應該實現JDBC 2.0應用程序接口,包括OptionalPackage接口XADataSource和XAConnection以及JTA接口XAResource。
應用程序服務器應該提供一個DataSource類,用來實現與分佈式事務基本結的交互以及一個鏈接池模塊(用於改善性能)。
分佈式事務處理的第一步就是應用程序要發送一個事務請求到事務管理程序。雖然最後的commit/rollback決定把事務做爲一個簡單的邏輯單元來對待,可是仍然可能會包括許多事務分支。一個事務分支與一個到包含在分佈式事務中的每一個資源管理程序相關聯。所以,到三個不一樣的關係數據庫管理的請求須要三個事務分支。每一個事務分支必須由本地資源管理程序提交或者返回。事務管理程序控制事務的邊界,而且負責最後決定應該提交或者返回的所有事務。這個決定由兩個步驟組成,稱爲Two - Phase Commit Protocol。
在第一步驟中,事務管理程序輪詢全部包含在分佈式事務中的資源管理程序(關係數據庫管理)來看看哪一個能夠準備提交。若是一個資源管理程序不能提交,它將不響應,而且把事務的特定部分返回,以便數據不被修改。
在第二步驟中,事務管理程序判斷否認響應的資源管理程序中是否有可以返回整個事務的。若是沒有否認響應的話,翻譯管理程序提交整個事務而且返回結果到應用程序中。
開發事項管理程序代碼的開發者必須與全部三個JTA接口有關:UserTransaction、TransactionManager和XAResource,這三個接口都被描述在
Sun JTA specification中。JDBC驅動程序開發者只須要關心XAResource接口。這個接口是容許一個資源管理程序參與事務的行業標準X/OpenXA協議的Java映射。鏈接XAResource接口的驅動程序組件負責在事務管理程序和資源管理程序之間擔任"翻譯"的任務。
三、容器事務
容器事務主要是J2EE應用服務器提供的,容器事務大可能是基於JTA完成,這是一個基於JNDI的,至關複雜的API實現。相對編碼實現JTA事務管理,咱們能夠經過EJB容器提供的容器事務管理機制(CMT)完成同一個功能,這項功能由J2EE應用服務器提供。這使得咱們能夠簡單的指定將哪一個方法加入事務,一旦指定,容器將負責事務管理任務。這是咱們土建的解決方式,由於經過這種方式咱們能夠將事務代碼排除在邏輯編碼以外,同時將全部困難交給J2EE容器去解決。使用EJB CMT的另一個好處就是程序員無需關心JTA API的編碼,不過,理論上咱們必須使用EJB。
一、JDBC事務控制的侷限性在一個數據庫鏈接內,可是其使用簡單。
二、JTA事務的功能強大,事務能夠跨越多個數據庫或多個DAO,使用也比較複雜。
三、容器事務,主要指的是J2EE應用服務器提供的事務管理,侷限於EJB應用使用。
事務控制是構建J2EE應用不可缺乏的一部分,合理選擇應用何種事務對整個應用系統來講相當重要。通常說來,在單個JDBC 鏈接鏈接的狀況下能夠選擇JDBC事務,在跨多個鏈接或者數據庫狀況下,須要選擇使用JTA事務,若是用到了EJB,則能夠考慮使用EJB容器事務。
在weblogic在對幾種JTA的應用場景進行的測試,總結以下:
測試代碼片斷:
public void doTest()throws Exception{
UserTransaction tx = null;
try{
Context ctx = new InitialContext();
tx =(UserTransaction)ctx.lookup("javax.transaction.UserTransaction");
tx.begin();
doResource1();
doResource2();
tx.commit();
}catch(Exception e){
e.printStackTrace();
if(tx != null){
tx.rollback();
}
}
}
private voiddoResource1()throws Exception{
...
DataSourceds = (DataSource)ctx.lookup("A|B|C|D|E");
con =ds.getConnection();
...
}
private voiddoResource2()throws Exception{
...
DataSourceds = (DataSource)ctx.lookup("A|B|C|D|E");
con =ds.getConnection();
...
}
共建立了五個鏈接池以及對應的數據源
A: OracleLocalDataSource
B: OracleLocalDataSource2
C: OracleXADataSource
D: OracleXADataSource2
E: MysqlLocalDataSource
A、B:【oracle.jdbc.driver.OracleDriver】
C、D:【oracle.jdbc.xa.client.OracleXADataSource】
E:【org.gjt.mm.mysql.Driver】
對於doResource1和doResource2所用不一樣數據源類型搭配測試狀況以下:
[A-A]:運行成功,且weblogic進行了優化,兩次操做得到的con實際上是同一個鏈接對象
[A-B]:運行失敗,不容許在一次事務中從不一樣的數據庫獲取local事務類型的鏈接
[A-E]:運行失敗,不容許在一次事務中從不一樣的數據庫獲取local事務類型的鏈接
[A-D]:在容許Emulate Two-Phase Commit for non-XA Driver的狀況下成功,不然失敗
[C-C]:運行成功,可是不像(A-A)的狀況,兩次得到con的對象不是同一個對象,weblogic併爲對該狀況進行優化
[C-D]:運行成功,這是典型的2PC(two-phase transaction commitprocess)用於分佈式多資源的應用狀況
對於C、D的XA類型驅動程序,weblogic默認不容許經過con.setAutoCommit(false)的方式進行事務啓動,能夠經過容許(SupportsLocal Transaction)選項啓動本地事務。
記得EJB的部署文件的事務屬性<trans-attribute>RequiresNew</trans-attribute>的狀況,在調用該EJB函數時若是已經存在一個事務進行中,那麼要求容器掛起該事務,啓動新的事務進行函數調用,直到函數結束後,再恢復原來的事務繼續進行。
也許你會想到用如下的方式進行:
UserTransaction tx =(UserTransaction)ctx.lookup("javax.transaction.UserTransaction");
UserTransaction tx2 = (UserTransaction)ctx.lookup("javax.transaction.UserTransaction");
tx.begin();
tx2.begin();
tx2.commit();
tx.commit();
以上代碼會拋出以下異常:
javax.transaction.NotSupportedException: Another transaction is associated withthis thread.
查找了sun的 JTA specification 說明以下:
The UserTransaction.begin method starts a global transaction and associates thetransaction with the calling thread. The transaction-to-thread association ismanaged transparently by the Transaction Manager. Support for nestedtranactions is not required. The UserTransaction.begin method throws theNotSupportedException when the calling thread is already associated with atransaction and the transaction manager implementation does not support nestedtransactions.
看來weblogic的Transaction沒有實現嵌套功能,那麼容器如何RequiresNew的ejb事務狀況呢,就得藉助於TransactionManager類了
tm =(TransactionManager)ctx.lookup("javax.transaction.TransactionManager");
tx = (UserTransaction)ctx.lookup("javax.transaction.UserTransaction");
tx.begin();
...
transaction = tm.suspend();
doNestedTransaction();
tm.resume(transaction);
...
tx.commit();
其實以上問題的順利解決都歸功於sun完整的官方資料,想一想從事Java快兩年了個人大部分知識都是來源於「東拼西湊」:書籍、論壇、項目...看來是該花點時間好好讀讀sun網站的各類specification了。
今天對XA和非XA驅動進行了更進一步的研究,終於搞清了之前些模菱兩可的問題。
經過測試得知,在JTA事務中(包括JDBC事務以及非事務環境下),應用程序操做的connection其實都是weblogic的包裝類
weblogic.jdbc.wrapper.JTSConnection_weblogic_jdbc_oracle_OracleConnection
weblogic.jdbc.wrapper.JTAConnection_weblogic_jdbc_wrapper_XAConnection_weblogic_jdbcx_base_BaseConnectionWrapper
weblogic.jdbc.wrapper.JTSConnection_com_mysql_jdbc_Connection
因爲XA驅動實現了XAResource的接口,因此能參與徹底的2PC協議,保證多資源參與的事務的原子操做。可是非XA驅動沒有實現XAResource的接口的接口,沒法徹底參與2PC協議,因此在分佈式事務(即JTA事務)中weblogic實現了非XA驅動的XAResource包裝(wrapper),用來模擬(或者說欺騙TM^_^)兩步提交,在...\bea\weblogic81\server\lib\weblogic.jar類包中,經過反編譯weblogic.jdbc.wrapper.JTSConnection和weblogic.jdbc.wrapperJTSXAResourceImpl類獲得以下代碼片斷:
JTSXAResourceImpl源碼片斷:
public int prepare(Xid xid)throws XAException
{
if(!jtsConn.getEnable2PC())
throw newXAException("JDBC driver does not support XA ... );
else
return 0;
}
public voidcommit(Xid xid, boolean flag)throws XAException
{
...
jtsConn.internalCommit();
...
}
public void rollback(Xid xid)throws XAException
{
...
jtsConn.internalRollback();
...
}
JTSConnection源碼片斷:
public synchronized void internalRollback() throwsSQLException
{
...
connection.rollback();
...
internalClose();
...
}
public voidinternalCommit() throws SQLException
{
...
connection.commit();
...
internalClose();
...
}
可知若是非XA驅動容許兩步提交時(enableTwoPhaseCommit),當TransactionManager調用prepare時XAResource包裝類只是簡單的返回XA_OK(0),當TransactionManager調用commit或rollback時XAResource包裝類將代理調用非XA驅動的JDBC connection的commit或rollback,因此若是在commit或rollback出現異常後,應用程序的數據將有可能處於不一致的狀態(其實若是XA驅動在TM調用XAResource的commit或者rollback時出錯,系統數據也會處於不一致的狀態,不過出現這種狀況的機率是微乎其微的,若是想搞三步、四步...提交的話,就會進入雞生蛋、蛋生雞的無休止討論的問題了^_^)。
接下來讓咱們研究一下鏈接關閉的問題,細心的人也許早已發現JTA與JDBC的事務對於應用層的操做有點「自相矛盾」,JDBC的先得到con在setAutoCommit(false)啓動事務,而後關閉con,在commit或者rollback事務,然而JTA的順序正好相反,先tx.begin(),再獲取con,而後關閉con,最後再tx.commit或者rollback。(這裏有句話您看完一下內容後會認同的:For both non-XAand XA driver, you can close the connection after the distributed transactionis completed.)
當應用程序調用Connection.close時容器經過註冊的ConnectionEventListener事件通知TransactionManager,以便TransactionManager結束Connection對應的XAResource對象的事務分支(end函數調用),對於XA驅動的鏈接此時在Connection.close以後便可將該鏈接返回XA鏈接池供其餘業務使用。
因此JTA spec中的提示到:
A distributed transaction maystill be active after a participating Connection object is closed. This is nottrue for local transactions。
可是對於非XA驅動調用Connection.close後的狀況將有全部區別,因爲XA驅動須要用connection進行最後的commit或rollback,因此應用程序調用Connection.close以後只是對與應用不能再使用包裝的Connection,但容器並無真正將鏈接返回鏈接池,而是在調用XAResource包裝類的commit和rollback時,進而調用JTSConnection的internalCommit和internalRollback,最終再JTSConnection的這兩個函數中internalClose將非XA的鏈接釋放到鏈接池中。
因此weblogic的資料(http://edocs.bea.com/wls/docs60/faq/transactions.html)中說:
the number of active distributed transactions using the non-XA
connection pool is limited by the maximum capacity of the JDBC connection pool
When you use an XA driver, theconnection management is more scalable. WLS does not hold on to the same physicalXA connection until the transaction is committed or rolled back. In fact, inmost cases, the XA connection as only held for the duration of a methodinvocation. WLS JDBC wrappers intercept all JDBC calls and enlist theXAResource associated with the XA connection on demand. When the methodinvocation returns to the caller, or when it makes another call to anotherserver, WLS delists the XAResource associated with the XA connection.
WLS also returns the XA connectionto the connection pool on delistment if there are no open result sets. Also,during commit processing, any XAResource object can be used to commit anynumber of distributed transactions in parallel. As a result, neither the numberof active distributed transactions using the XA connection pool nor the numberof concurrent commit/rollbacks is limited by the maximum capacity of theconnection pool. Only the number of concurrent database access connections islimited by the maximum capacity of the connection pool.
對於以上XA驅動的con在關閉後,沒必要等待事務結束即釋放回鏈接池的推論,我在weblogic上對oracle作了些好像沒有效果,weblogic中有個 Keep XA Connection Till Transaction Complete 的選項我也沒有選中啊。不知是我對JTA的理解有誤,仍是說與我用的數據庫驅動或者是weblogic的實現有關,有時間要好好研究一下了。
最後請注意:除非將XA驅動的鏈接池設置容許【Supports Local Transaction】選項,不然在非事務的環境下對con進行的操做將拋出以下錯誤,甚至是getAutoCommit()操做
剛看完《hibernate in action》,前段時間hiberante3又發佈了3.0.2版,對於hibernate的這種更新路線我仍是比較喜歡的,2.x的版本繼續更新發展這對於已經在項目中應用hibernate的人來講是再慶幸不過的了(不過這也許是廢話,若是GAVIN KING不繼續發展2.x誰還敢用3.x,由於...4.x...),3版本是不兼容2的,總體包名都進行了完全的變更,若是想移植的話其實工做量也不大不少接口都是同樣的,配置文件也儘可能保持之前的規範,並且3會有更多使人興奮的新特性,這種走不一樣版本分支、不拖泥帶水的革新,至少讓我感受比一味堅持要兼容老版本的EJB3來得爽!
下面我還來說講hibernate中的JTA事務應用。
本人對於hibernate我仍是比較喜歡的,特別是在領域驅動設計開發,徹底消除了面向對象與面向關係(數據庫)的抗阻,真的很爽,(不是很喜歡老的開發方法,一開始就分析系統有多少個實體,有多少數據表)
//////////////如下爲hibernate中的經典事務操做步驟 //////////////
Session sess = factory.openSession();
Transaction tx = null;
try {
tx = sess.beginTransaction();
// do some work
...
tx.commit();
}
catch (RuntimeException e) {
if (tx != null) tx.rollback();
throw e; // or display error message
}
finally {
sess.close();
}
hibernate2中只有JDBCTransaction和JTATransaction兩種事務類,對於使用JTA事務的應用,
應該說JTATransaction適用於絕大部分狀況,可是CMT狀況將存在一些例外:
////////// begin片斷 //////////
newTransaction = ut.getStatus() ==Status.STATUS_NO_TRANSACTION;
if (newTransaction) {
ut.begin();
log.debug("Began a new JTA transaction");
}
////////// commit片斷 //////////
if (session.getFlushMode()!=FlushMode.NEVER ) session.flush();
if (newTransaction) {
try {
log.debug("Committing UserTransaction started by Hibernate");
ut.commit();
}
////////// rollback片斷 //////////
if (newTransaction) {
if (!commitFailed) ut.rollback();
}
else {
ut.setRollbackOnly();
}
經過以上JTATransaction源碼可知,若是調用session.beginTransaction()時已經處於事務狀態,hibernate只是簡單的加入這個事務,這對於Requires和RequiresNew等狀況是沒有問題的,可是若是調用session.beginTransaction()時不處於事務環境,那麼JTATransaction將啓動事務。這對於一個經過容器管理(CMT)事務的且不須要啓事務的EJB調用將會存在矛盾。固然對於CMT的狀況你能夠不調用任何hibernate的Transaction事務函數,只經過session進行CRUD(create、read、update、delete)操做,避開這個例外的狀況,可是這存在一個新問題:通常的hibernate操做代碼並不直接手工調用session.flush,而是經過tx.commit時由hibernate內部自動進行flush,因此若是想用以上的小伎倆,那麼請記得在操做最後手工添加session.flush函數。這樣CMT中的代碼片斷能夠改造以下:
Session sess =factory.openSession();
try {
// do some work
...
session.flush();
}
catch (RuntimeException e) {
context.setRollbackOnly();
throw e; // or display error message
}
finally {
sess.close();
}
爲了解決以上問題hibernate3進行了改進,增長了CMTTransaction類,以及兩個新屬性:
1:【hibernate.transaction.flush_before_completion】
If enabled, the session will be automatically flushed during the beforecompletion
phase of the transaction. (Very useful when using Hibernate with CMT.)
2:【hibernate.transaction.auto_close_session】
If enabled, the session will be automatically closed during the beforecompletion
phase of the transaction.(Very useful when using Hibernate with CMT.)
因此對於CMT的狀況,只要將以上兩個參數設置爲true,hibernate自動會在事務提交時進行flush和close,具體實現細節能夠看看org.hibernate.transaction.CacheSynchronization的實現和
JDBCContext中的registerSynchronizationIfPossible函數。因爲CMT狀況下容器對於RuntimeException的異常將進行事務回滾,因此能夠經過在須要回滾事務時拋出RuntimeException類型的異常,那麼甚至能夠徹底不用操做hibernate的Transaction類的任何API。
對於JTA的配置問題注意如下幾點:
tx = (UserTransaction)ctx.lookup("javax.transaction.UserTransaction");
tx = (UserTransaction) ctx.lookup("java:comp/UserTransaction");
對於weblogic因爲以上兩種方式都能找到JTA事務對象,而hibernate默認的查找名以下爲【java:comp/UserTransaction】,因此在weblogic中設置啓用JTA方式,只須要配置【hibernate.transaction.factory_class】屬性爲【org.hibernate.transaction.JTATransactionFactory】,【hibernate.transaction.manager_lookup_class】屬性不配也行。
還有一種方式經過配置以下屬性,能夠指定UserTransaction的JNDI名
<property name="jta.UserTransaction">javax.transaction.UserTransaction</property>
另外還有一個JTA調用超時問題,對於weblogic默認是30秒,能夠經過控制檯進行動態配置,若是事務處理操做配置的超時時間對於weblogic的狀況,容器將會自動調用internalRollback()。
最後一點須要注意的是數據庫事務隔離級別的設置:
----------------------------------------------------------------
■ Readuncommitted:
這個級別是不安全的,事務中的查詢會讀到當前其它事務正在設置當時還未提交的數據
■ Readcommitted:
這個級別相對比較安全,事務中讀到的數據都是已經獲得提交的數據,可是若是兩次讀取同一個條記錄,可是在兩次讀取的過程當中有另外的事務更改了改記錄併成功提交的話,則會出現同一事務中兩次讀取同一條記錄數據不一致的狀況。這種狀況不多出現,由於通常同一事務的程序不會重複讀取同一條記錄,若是用hibernate就更安全了,hibernate的一級緩存不會讓程序向數據庫兩次讀取同一條記錄。
■ Repeatable read:
這個級別解決了同一事務兩次讀取數據結果不一樣的狀況,這個級別也是不少數據庫的默認事務級別(如mysql)
■Serializable:
這個級別會使全部事務串行化工做,每一個事務只能排隊進行數據庫操做,相似單線程的Servlet的工做機制,這樣在並不是量較高的數據庫訪問時,數據庫操做效率將極其底下,應該避免使用
----------------------------------------------------------------
hibernate中經過【hibernate.connection.isolation】屬性進行設置,可是若是hibernate的數據庫鏈接是經過數據源得到的話,hibernate則再也不對事務隔離級別進行設置,因此對於數據源的到的數據庫鏈接只能經過設置應用服務器配置數據庫隔離級別,固然也能夠經過Connection con=session.connection();con.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);進行手工設置。