Java事務處理總結
一、什麼是Java事務
事務必須服從ISO/IEC所制定的ACID原則。ACID是原子性(atomicity)、一致性(consistency)、隔離性(isolation)和永續性(durability)的縮寫。事務的原子性表示事務執行過程中的任何失敗都將導致事務所做的任何修改失效。一致性表示當事務執行失敗時,所有被該事務影響的資料都應該恢復到事務執行前的狀態。隔離性表示在事務執行過程中對資料的修改,在事務提交之前對其他事務不可見。永續性表示已提交的資料在事務執行失敗時,資料的狀態都應該正確。
通俗的理解,事務是一組原子操作單元,從資料庫角度說,就是一組SQL指令,要麼全部執行成功,若因為某個原因其中一條指令執行有錯誤,則撤銷先前執行過的所有指令。更簡答的說就是:要麼全部執行成功,要麼撤銷不執行。
既然事務的概念從資料庫而來,那Java事務是什麼?之間有什麼聯絡?
實際上,一個Java應用系統,如果要操作資料庫,則通過JDBC來實現的。增加、修改、刪除都是通過相應方法間接來實現的,事務的控制也相應轉移到Java程式程式碼中。因此,資料庫操作的事務習慣上就稱為Java事務。
二、為什麼需要事務
事務是為解決資料安全操作提出的,事務控制實際上就是控制資料的安全訪問。具一個簡單例子:比如銀行轉帳業務,賬戶A要將自己賬戶上的1000元轉到B賬戶下面,A賬戶餘額首先要減去1000元,然後B賬戶要增加1000元。假如在中間網路出現了問題,A賬戶減去1000元已經結束,B因為網路中斷而操作失敗,那麼整個業務失敗,必須做出控制,要求A賬戶轉帳業務撤銷。這才能保證業務的正確性,完成這個操走就需要事務,將A賬戶資金減少和B賬戶資金增加方到一個事務裡面,要麼全部執行成功,要麼操作全部撤銷,這樣就保持了資料的安全性。
三、Java事務的型別
Java事務的型別有三種:JDBC事務、JTA(JavaTransaction API)事務、容器事務。
1、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 事務不能跨越多個數據庫。
2、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的三個介面部分:
1、UserTransaction,javax.transaction.UserTransaction介面提供能夠程式設計地控制事務處理範圍的應用程式。 javax.transaction.UserTransaction方法開啟一個全域性事務並且使用呼叫執行緒與事務處理關聯。
2、Transaction Manager,javax.transaction.TransactionManager介面允許應用程式伺服器來控制代表正在管理的應用程式的事務範圍。
3、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介面的驅動程式元件負責在事務管理程式和資源管理程式之間擔任"翻譯"的任務。
3、容器事務
容器事務主要是J2EE應用伺服器提供的,容器事務大多是基於JTA完成,這是一個基於JNDI的,相當複雜的API實現。相對編碼實現JTA事務管理,我們可以通過EJB容器提供的容器事務管理機制(CMT)完成同一個功能,這項功能由J2EE應用伺服器提供。這使得我們可以簡單的指定將哪個方法加入事務,一旦指定,容器將負責事務管理任務。這是我們土建的解決方式,因為通過這種方式我們可以將事務程式碼排除在邏輯編碼之外,同時將所有困難交給J2EE容器去解決。使用EJB CMT的另外一個好處就是程式設計師無需關心JTA API的編碼,不過,理論上我們必須使用EJB。
四、三種事務差異
1、JDBC事務控制的侷限性在一個數據庫連線內,但是其使用簡單。
2、JTA事務的功能強大,事務可以跨越多個數據庫或多個DAO,使用也比較複雜。
3、容器事務,主要指的是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)
這個級別會使所有事務序列化工作,每個事務只能排隊進行資料庫操作,類似單執行緒的Servlet的工作機制,這樣在並非量較高的資料庫訪問時,資料庫操作效率將極其底下,應該避免使用
----------------------------------------------------------------
hibernate中通過【hibernate.connection.isolation】屬性進行設定,但是如果hibernate的資料庫連線是通過資料來源獲得的話,hibernate則不再對事務隔離級別進行設定,所以對於資料來源的到的資料庫連線只能通過設定應用伺服器配置資料庫隔離級別,當然也可以通過Connection con=session.connection();con.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);進行手工設定。
相關推薦
Java事務處理總結
一、什麼是Java事務 事務必須服從ISO/IEC所制定的ACID原則。ACID是原子性(atomicity)、一致性(consistency)、隔離性(isolation)和永續性(durability)的縮寫。事務的原子性表示事務執行過程中的任何失敗都將導致事務所做的任
java事務處理全解析
成功 spa 做了 開發 overflow lan 進行 訪問 ksh 最近學習java事務,看到一位前輩的系列博客不錯,轉載過來作為記錄 轉載地址:http://www.davenkin.me/post/2013-02-16/40048284001 (一)Jav
Java異常處理總結
tst error 有一個 ror 而是 阻止 cep 行處理 編碼 一、Java 異常繼承框架 Error: Error類對象由 Java 虛擬機生成並拋出,大多數錯誤與代碼編寫者所執行的操作無關。對於設計合理的應用程序來說,即使確實發生了錯誤,本質上也不應該試圖去處理
java日期處理 java日期處理總結
轉載:https://www.cnblogs.com/lcngu/p/5154834.html java日期處理總結 Java日期時間使用總結 一、Java中的日期概述 &
Java事務處理全解析(七)—— 像Spring一樣使用Transactional註解(Annotation)
在本系列的上一篇文章中,我們講到了使用動態代理的方式完成事務處理,這種方式將service層的所有public方法都加入到事務中,這顯然不是我們需要的,需要代理的只是那些需要操作資料庫的方法。在本篇中,我們將講到如何使用Java註解(Annotation)來標記需要事務處
資料庫事務(二): java事務處理
在平時我們做業務開發的時候,資料庫操作一般都需要使用到事務。如果是基於spring的專案,很簡單,有兩種方法: 1.配置一個DataSource給spring容器託管,再配置一個TransactionManager事務管理器,然後在需要事務的方法上加上Tran
java 檔案處理總結
前言: 一直以來,飽受檔案路徑的困惑,自己翻閱印象筆記中記錄的此類記錄,發現很多都是雜亂,根本不能簡單話的解釋這個問題。本篇的目的是總結以前的筆記,加上自己測試的例子,能明白準確的記錄下這個問題。內容的話僅包含常見的java程式讀取檔案,不包含java
Java 異常處理的誤區和經驗總結
ORC 進一步 相關 ror final 額外 檢測 業務 清理資源 一 異常分檢測異常和非檢測異常,異常的應用情景可以概括為以下: 調用代碼不能繼續執行,需要立即終止。出現這種情況的可能性太多太多,例如服務器連接不上、參數不正確等。這些時候都適用非檢測異常,不需要調用
Spring事務處理的實現:Spring事務總結
這篇我想對Spring事務機制進行一次總結,總結的方式也和AOP類似那就是使用圖解的方式。首先我們需要對我們事務的AOP機制進行初始化,也就是宣告要對那些方法(切面)進行增強,這裡涉及到了TransactionInterceptor攔截器鏈的生成。 接著書上講述了事務處理配置的讀入。
005 異常處理 java基礎學習總結——異常處理
java基礎學習總結——異常處理 一、異常的概念 異常指的是執行期出現的錯誤,也就是當程式開始執行以後執行期出現的錯誤。出現錯誤時觀察錯誤的名字和行號最為重要。 1 package cn.javastudy.summary; 2 3 p
java基礎學習總結(十三):Java異常處理
一、JAVA異常 異常是指不期而至的各種情況,如:檔案找不到、網路連線失敗、非法引數等。異常是一個事件,它發生在程式執行期間,干擾了正常的指令流程。Java通過API中的Throwable類的眾多子類描述各種不同的異常。因而,Java異常都是物件,是Th
Java byte資料轉換和處理總結
一.byte和int相互轉換的方法 java程式或Android程式的socket資料傳輸,都是通過byte陣列,但是int型別是4個byte組成的,如何把一個整形int轉換成byte陣列,同時如何把一個長度為4的byte陣列轉換為int型別。 /** * int到byte[]
總結-java異常處理
異常處理 前言:識別錯誤,響應錯誤的一種機制,有效的異常處理能夠加強程式的健壯性,易於除錯。 異常是一種強大的除錯手段,在於回答了以下三個問題: 1,什麼出錯了? 2,那裡出錯了? 3,為什麼出錯? 在有效使用異常的情況下,異常型別回答了“什麼”被丟擲,異常堆疊跟蹤回答了“
java資料庫程式設計(12)事務處理
Connection是預設將executeXXX(String sql)執行之後馬上提交給資料庫的,這樣一來,有時候如果需要處理一連串的sql語句(也就是事務,這裡不講解事務的相關知識),則需要將Connection的自動提交關掉,使用的方法為setAutoCommit(false)。在將事務
Java處理高併發量訪問的處理總結
結合之前做的一個網站,專案中分了幾個子專案,主要用到Redis,service(server)層和control層分離,有做了快取,頁面也是進行靜態化(htm和freemarker),仔細想想,整個專案基本吻合高併發,負載均衡的處理。在網上找了些資料,基本和專案的特點吻合,特別紀念一下,但是後面的一
UpdateBatch與事務處理的一點總結
對於某些設定或者提交,如果希望是全部修改完畢後才確定生效,可以將DataSet的LockType:=ltBatchOptimistic,這樣就可以了。然後每次做的修改和改動都暫時儲存在快取中,必須通過UpdateBatch來提交入庫。可以通過判斷DataSet的UpdateStatus屬性是否為usUnmod
Java EE專案中異常設計及處理總結
異常,為我們處理非正常的業務流程提供了很好的解決方案,如果你有過dbase、c、pascal等過程式語言開發的經歷,你一定會深刻體會到,異常機制給你的程式碼可讀行、可維護性帶來的好處,同時,程式的健壯性也得到了增強。 在 java專案中,異常設計要注意下面的幾點。 一、自定義異常父類的選擇 A、自定義異常的
java基礎之字串處理總結
Java中的字串處理主要有下面三個類來處理的:String、StringBuffer、StringBuilder。三者區別綜述:1,String、StringBuffer、StringBuilder都是
Java中怎樣實現批量刪除操作(Java對資料庫進行事務處理)?
本人開發的一個安卓版app小遊戲,瘋狂猜明星android版,圖示看起來很搞笑,有點京劇變臉的味道。朋友們小手一抖,下載支援下。謝謝了 本文是記錄Java中實現批量刪除操作(Java對資料庫進行事務處理),在開始之前先來看下面這樣的一個頁面圖: 上面這張圖片顯示的是從
JAVA WEB -事務處理
1.事務處理 1.1 事務處理型別 mysql JDBC DBUtils 1.2 Mysql事務處理 首先,開啟小海豚,建立表,並輸入資料。 CREATE TABLE account( id INT PRIMAR