日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Spring 事务机制详解

發(fā)布時間:2025/3/21 javascript 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring 事务机制详解 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

Spring事務(wù)機制主要包括聲明式事務(wù)和編程式事務(wù),此處側(cè)重講解聲明式事務(wù),編程式事務(wù)在實際開發(fā)中得不到廣泛使用,僅供學(xué)習(xí)參考。

Spring聲明式事務(wù)讓我們從復(fù)雜的事務(wù)處理中得到解脫。使得我們再也無需要去處理獲得連接、關(guān)閉連接、事務(wù)提交和回滾等這些操作。再也無需要我們在與事務(wù)相關(guān)的方法中處理大量的try…catch…finally代碼。我們在使用Spring聲明式事務(wù)時,有一個非常重要的概念就是事務(wù)屬性。事務(wù)屬性通常由事務(wù)的傳播行為,事務(wù)的隔離級別,事務(wù)的超時值和事務(wù)只讀標志組成。我們在進行事務(wù)劃分時,需要進行事務(wù)定義,也就是配置事務(wù)的屬性。

下面分別詳細講解,事務(wù)的四種屬性,僅供諸位學(xué)習(xí)參考:

Spring在TransactionDefinition接口中定義這些屬性,以供PlatfromTransactionManager使用, PlatfromTransactionManager是spring事務(wù)管理的核心接口。

1 2 3 4 5 6 public?interface?TransactionDefinition { int?getPropagationBehavior();//返回事務(wù)的傳播行為。 int?getIsolationLevel();//返回事務(wù)的隔離級別,事務(wù)管理器根據(jù)它來控制另外一個事務(wù)可以看到本事務(wù)內(nèi)的哪些數(shù)據(jù)。 int?getTimeout();//返回事務(wù)必須在多少秒內(nèi)完成。 boolean?isReadOnly();//事務(wù)是否只讀,事務(wù)管理器能夠根據(jù)這個返回值進行優(yōu)化,確保事務(wù)是只讀的。 }

1. TransactionDefinition接口中定義五個隔離級別:

ISOLATION_DEFAULT 這是一個PlatfromTransactionManager默認的隔離級別,使用數(shù)據(jù)庫默認的事務(wù)隔離級別.另外四個與JDBC的隔離級別相對應(yīng);

ISOLATION_READ_UNCOMMITTED 這是事務(wù)最低的隔離級別,它充許別外一個事務(wù)可以看到這個事務(wù)未提交的數(shù)據(jù)。這種隔離級別會產(chǎn)生臟讀,不可重復(fù)讀和幻像讀。

ISOLATION_READ_COMMITTED? 保證一個事務(wù)修改的數(shù)據(jù)提交后才能被另外一個事務(wù)讀取。另外一個事務(wù)不能讀取該事務(wù)未提交的數(shù)據(jù)。這種事務(wù)隔離級別可以避免臟讀出現(xiàn),但是可能會出現(xiàn)不可重復(fù)讀和幻像讀。

ISOLATION_REPEATABLE_READ? 這種事務(wù)隔離級別可以防止臟讀,不可重復(fù)讀。但是可能出現(xiàn)幻像讀。它除了保證一個事務(wù)不能讀取另一個事務(wù)未提交的數(shù)據(jù)外,還保證了避免下面的情況產(chǎn)生(不可重復(fù)讀)。

ISOLATION_SERIALIZABLE 這是花費最高代價但是最可靠的事務(wù)隔離級別。事務(wù)被處理為順序執(zhí)行。除了防止臟讀,不可重復(fù)讀外,還避免了幻像讀。

1: Dirty reads(臟讀)。也就是說,比如事務(wù)A的未提交(還依然緩存)的數(shù)據(jù)被事務(wù)B讀走,如果事務(wù)A失敗回滾,會導(dǎo)致事務(wù)B所讀取的的數(shù)據(jù)是錯誤的。
2: non-repeatable reads(數(shù)據(jù)不可重復(fù)讀)。比如事務(wù)A中兩處讀取數(shù)據(jù)-total-的值。在第一讀的時候,total是100,然后事務(wù)B就把total的數(shù)據(jù)改成200,事務(wù)A再讀一次,結(jié)果就發(fā)現(xiàn),total竟然就變成200了,造成事務(wù)A數(shù)據(jù)混亂。
3: phantom reads(幻象讀數(shù)據(jù)),這個和non-repeatable reads相似,也是同一個事務(wù)中多次讀不一致的問題。但是non-repeatable reads的不一致是因為他所要取的數(shù)據(jù)集被改變了(比如total的數(shù)據(jù)),但是phantom reads所要讀的數(shù)據(jù)的不一致卻不是他所要讀的數(shù)據(jù)集改變,而是他的條件數(shù)據(jù)集改變。比如Select account.id where account.name=”ppgogo*”,第一次讀去了6個符合條件的id,第二次讀取的時候,由于事務(wù)b把一個帳號的名字由”dd”改成”ppgogo1″,結(jié)果取出來了7個數(shù)據(jù)。

2. 在TransactionDefinition接口中定義了七個事務(wù)傳播行為:

(1)PROPAGATION_REQUIRED 如果存在一個事務(wù),則支持當(dāng)前事務(wù)。如果沒有事務(wù)則開啟一個新的事務(wù)。

Java代碼:

1 2 3 4 5 6 7 8 9 10 11 //事務(wù)屬性 PROPAGATION_REQUIRED methodA{ …… methodB(); …… } //事務(wù)屬性 PROPAGATION_REQUIRED methodB{ ???…… }

使用spring聲明式事務(wù),spring使用AOP來支持聲明式事務(wù),會根據(jù)事務(wù)屬性,自動在方法調(diào)用之前決定是否開啟一個事務(wù),并在方法執(zhí)行之后決定事務(wù)提交或回滾事務(wù)。

單獨調(diào)用methodB方法:

Java代碼

1 2 3 4 5 main{ metodB(); }

相當(dāng)于

Java代碼

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 Main{ Connection con=null; try{ con = getConnection(); con.setAutoCommit(false); //方法調(diào)用 methodB(); //提交事務(wù) con.commit(); } Catch(RuntimeException ex){ ????????????//回滾事務(wù) con.rollback();?? } finally{ //釋放資源 closeCon(); } }

Spring保證在methodB方法中所有的調(diào)用都獲得到一個相同的連接。在調(diào)用methodB時,沒有一個存在的事務(wù),所以獲得一個新的連接,開啟了一個新的事務(wù)。

單獨調(diào)用MethodA時,在MethodA內(nèi)又會調(diào)用MethodB.

執(zhí)行效果相當(dāng)于:

Java代碼

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 ?????????main{ Connection con = null; try{ con = getConnection(); ????methodA(); con.commit(); } catch(RuntimeException ex){ con.rollback(); } finally{ ???closeCon(); }? }

調(diào)用MethodA時,環(huán)境中沒有事務(wù),所以開啟一個新的事務(wù).當(dāng)在MethodA中調(diào)用MethodB時,環(huán)境中已經(jīng)有了一個事務(wù),所以methodB就加入當(dāng)前事務(wù)。

(2)PROPAGATION_SUPPORTS 如果存在一個事務(wù),支持當(dāng)前事務(wù)。如果沒有事務(wù),則非事務(wù)的執(zhí)行。但是對于事務(wù)同步的事務(wù)管理器,PROPAGATION_SUPPORTS與不使用事務(wù)有少許不同。

Java代碼:

1 2 3 4 5 6 7 8 9 //事務(wù)屬性 PROPAGATION_REQUIRED methodA(){ ??methodB(); } //事務(wù)屬性 PROPAGATION_SUPPORTS methodB(){ ??…… }

單純的調(diào)用methodB時,methodB方法是非事務(wù)的執(zhí)行的。當(dāng)調(diào)用methdA時,methodB則加入了methodA的事務(wù)中,事務(wù)地執(zhí)行。

(3)PROPAGATION_MANDATORY 如果已經(jīng)存在一個事務(wù),支持當(dāng)前事務(wù)。如果沒有一個活動的事務(wù),則拋出異常。

Java代碼:

1 2 3 4 5 6 7 8 9 //事務(wù)屬性 PROPAGATION_REQUIRED ????methodA(){ ??methodB(); ????????????????} ????//事務(wù)屬性 PROPAGATION_MANDATORY ????methodB(){ ????…… ????}

當(dāng)單獨調(diào)用methodB時,因為當(dāng)前沒有一個活動的事務(wù),則會拋出異常throw new IllegalTransactionStateException(“Transaction propagation ‘mandatory’ but no existing transaction found”);當(dāng)調(diào)用methodA時,methodB則加入到methodA的事務(wù)中,事務(wù)地執(zhí)行。

(4)PROPAGATION_REQUIRES_NEW 總是開啟一個新的事務(wù)。如果一個事務(wù)已經(jīng)存在,則將這個存在的事務(wù)掛起。

Java代碼:

1 2 3 4 5 6 7 8 9 10 11 //事務(wù)屬性 PROPAGATION_REQUIRED methodA(){ ???doSomeThingA(); methodB(); doSomeThingB(); } //事務(wù)屬性 PROPAGATION_REQUIRES_NEW methodB(){ ???…… }

Java代碼:

1 2 3 main(){ ??methodA(); }

相當(dāng)于

Java代碼:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 main(){ ??TransactionManager tm = null; try{ ??//獲得一個JTA事務(wù)管理器 ????tm = getTransactionManager(); ????tm.begin();//開啟一個新的事務(wù) ????Transaction ts1 = tm.getTransaction(); ????doSomeThing(); ????tm.suspend();//掛起當(dāng)前事務(wù) ????try{ ??????tm.begin();//重新開啟第二個事務(wù) ??????Transaction ts2 = tm.getTransaction(); ??????methodB(); ??????ts2.commit();//提交第二個事務(wù) ???} ??Catch(RunTimeException ex){ ??????ts2.rollback();//回滾第二個事務(wù) ??} ??finally{ ?????//釋放資源 ???} ????//methodB執(zhí)行完后,復(fù)恢第一個事務(wù) ????tm.resume(ts1); doSomeThingB(); ????ts1.commit();//提交第一個事務(wù) } catch(RunTimeException ex){ ???ts1.rollback();//回滾第一個事務(wù) } finally{ ???//釋放資源 } }

在這里,我把ts1稱為外層事務(wù),ts2稱為內(nèi)層事務(wù)。從上面的代碼可以看出,ts2與ts1是兩個獨立的事務(wù),互不相干。Ts2是否成功并不依賴于ts1。如果methodA方法在調(diào)用methodB方法后的doSomeThingB方法失敗了,而methodB方法所做的結(jié)果依然被提交。而除了methodB之外的其它代碼導(dǎo)致的結(jié)果卻被回滾了。使用PROPAGATION_REQUIRES_NEW,需要使用JtaTransactionManager作為事務(wù)管理器。
(5)PROPAGATION_NOT_SUPPORTED? 總是非事務(wù)地執(zhí)行,并掛起任何存在的事務(wù)。使用PROPAGATION_NOT_SUPPORTED,也需要使用JtaTransactionManager作為事務(wù)管理器。(代碼示例同上,可同理推出)

(6)PROPAGATION_NEVER 總是非事務(wù)地執(zhí)行,如果存在一個活動事務(wù),則拋出異常;

(7)PROPAGATION_NESTED如果一個活動的事務(wù)存在,則運行在一個嵌套的事務(wù)中. 如果沒有活動事務(wù), 則按TransactionDefinition.PROPAGATION_REQUIRED 屬性執(zhí)行。這是一個嵌套事務(wù),使用JDBC 3.0驅(qū)動時,僅僅支持DataSourceTransactionManager作為事務(wù)管理器。需要JDBC 驅(qū)動的java.sql.Savepoint類。有一些JTA的事務(wù)管理器實現(xiàn)可能也提供了同樣的功能。使用PROPAGATION_NESTED,還需要把PlatformTransactionManager的nestedTransactionAllowed屬性設(shè)為true;而nestedTransactionAllowed屬性值默認為false;

Java代碼:

1 2 3 4 5 6 7 8 9 10 11 //事務(wù)屬性 PROPAGATION_REQUIRED methodA(){ ???doSomeThingA(); ???methodB(); ???doSomeThingB(); } //事務(wù)屬性 PROPAGATION_NESTED methodB(){ ??…… }

如果單獨調(diào)用methodB方法,則按REQUIRED屬性執(zhí)行。如果調(diào)用methodA方法,相當(dāng)于下面的效果:

Java代碼:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 main(){ Connection con = null; Savepoint savepoint = null; try{ ???con = getConnection(); ???con.setAutoCommit(false); ???doSomeThingA(); ???savepoint = con2.setSavepoint(); ???try{ ???????methodB(); ???}catch(RuntimeException ex){ ??????con.rollback(savepoint); ???} ???finally{ ?????//釋放資源 ??} ???doSomeThingB(); ???con.commit(); } catch(RuntimeException ex){ ??con.rollback(); } finally{ ???//釋放資源 } }

當(dāng)methodB方法調(diào)用之前,調(diào)用setSavepoint方法,保存當(dāng)前的狀態(tài)到savepoint。如果methodB方法調(diào)用失敗,則恢復(fù)到之前保存的狀態(tài)。但是需要注意的是,這時的事務(wù)并沒有進行提交,如果后續(xù)的代碼(doSomeThingB()方法)調(diào)用失敗,則回滾包括methodB方法的所有操作。

嵌套事務(wù)一個非常重要的概念就是內(nèi)層事務(wù)依賴于外層事務(wù)。外層事務(wù)失敗時,會回滾內(nèi)層事務(wù)所做的動作。而內(nèi)層事務(wù)操作失敗并不會引起外層事務(wù)的回滾。

PROPAGATION_NESTED 與PROPAGATION_REQUIRES_NEW的區(qū)別:它們非常類似,都像一個嵌套事務(wù),如果不存在一個活動的事務(wù),都會開啟一個新的事務(wù)。使用PROPAGATION_REQUIRES_NEW時,內(nèi)層事務(wù)與外層事務(wù)就像兩個獨立的事務(wù)一樣,一旦內(nèi)層事務(wù)進行了提交后,外層事務(wù)不能對其進行回滾。兩個事務(wù)互不影響。兩個事務(wù)不是一個真正的嵌套事務(wù)。同時它需要JTA事務(wù)管理器的支持。

使用PROPAGATION_NESTED時,外層事務(wù)的回滾可以引起內(nèi)層事務(wù)的回滾。而內(nèi)層事務(wù)的異常并不會導(dǎo)致外層事務(wù)的回滾,它是一個真正的嵌套事務(wù)。DataSourceTransactionManager使用savepoint支持PROPAGATION_NESTED時,需要JDBC 3.0以上驅(qū)動及1.4以上的JDK版本支持。其它的JTA TrasactionManager實現(xiàn)可能有不同的支持方式。

PROPAGATION_REQUIRES_NEW 啟動一個新的, 不依賴于環(huán)境的 “內(nèi)部” 事務(wù). 這個事務(wù)將被完全 commited 或 rolled back 而不依賴于外部事務(wù), 它擁有自己的隔離范圍, 自己的鎖, 等等. 當(dāng)內(nèi)部事務(wù)開始執(zhí)行時, 外部事務(wù)將被掛起, 內(nèi)務(wù)事務(wù)結(jié)束時, 外部事務(wù)將繼續(xù)執(zhí)行。

另一方面, PROPAGATION_NESTED 開始一個 “嵌套的” 事務(wù),? 它是已經(jīng)存在事務(wù)的一個真正的子事務(wù). 潛套事務(wù)開始執(zhí)行時,? 它將取得一個 savepoint. 如果這個嵌套事務(wù)失敗, 我們將回滾到此 savepoint. 潛套事務(wù)是外部事務(wù)的一部分, 只有外部事務(wù)結(jié)束后它才會被提交。

由此可見, PROPAGATION_REQUIRES_NEW 和 PROPAGATION_NESTED 的最大區(qū)別在于, PROPAGATION_REQUIRES_NEW 完全是一個新的事務(wù), 而 PROPAGATION_NESTED 則是外部事務(wù)的子事務(wù), 如果外部事務(wù) commit, 潛套事務(wù)也會被 commit, 這個規(guī)則同樣適用于 roll back.
PROPAGATION_REQUIRED應(yīng)該是我們首先的事務(wù)傳播行為。它能夠滿足我們大多數(shù)的事務(wù)需求。


from:?https://my.oschina.net/xianggao/blog/84237?fromerr=ReFPLSuv

http://www.cnblogs.com/csniper/p/5536633.html

總結(jié)

以上是生活随笔為你收集整理的Spring 事务机制详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。