国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - Java教程 - spring事務(wù)Propagation及其實現(xiàn)原理詳解

spring事務(wù)Propagation及其實現(xiàn)原理詳解

2021-04-01 11:30那個天真的人 Java教程

這篇文章主要介紹了spring事務(wù)Propagation及其實現(xiàn)原理詳解,分享了相關(guān)代碼示例,小編覺得還是挺不錯的,具有一定借鑒價值,需要的朋友可以參考下

本文研究的主要是spring事務(wù)Propagation及其實現(xiàn)原理,具體介紹如下。

 

簡介

 

spring目前已是java開發(fā)的一個事實標(biāo)準(zhǔn),這得益于它的便利、功能齊全、容易上手等特性。在開發(fā)過程當(dāng)中,操作DB是非常常見的操作,而涉及到db,就會涉及到事務(wù)。事務(wù)在平時的開發(fā)過程當(dāng)中,就算沒有注意到,程序正常執(zhí)行不會有副作用,但如果出現(xiàn)了異常,而又沒有處理好事務(wù)的話,可能就會出現(xiàn)意想不到的結(jié)果。spring在事務(wù)方面進行了各種操作的封裝,特別是聲明式事務(wù)的出現(xiàn),讓開發(fā)變得更加的舒心。spring對事務(wù)進行了擴展,支持定義多種傳播屬性,這也是本篇要說明的重點。

 

事務(wù)是什么

 

非嚴(yán)格的講,一個事務(wù)是多個操作的簡稱,這些操作要么全部生效,要么一個都不生效(相當(dāng)于沒有執(zhí)行過),一個通用的操作流程簡化如下:

?
1
2
3
4
5
6
7
8
try{
 Connection conn = getConnection();
 // 執(zhí)行一些數(shù)據(jù)庫操作
}catch(Exception e){
  conn.rollback();
}finally{
 conn.close();
}

從以上代碼可以看出一些問題:

  • 太多無用的固定代碼
  • 如果一個請求需要調(diào)用多個服務(wù)接口,難以更精細(xì)的控制事務(wù)
  • 跨多種底層數(shù)據(jù)層,如jdbc,mybatis,hibernate,jta,難以統(tǒng)一編碼方式。
  •  

spring提供了聲明式事務(wù),使得我們不用關(guān)注底層的具體實現(xiàn),屏蔽了多種不同的底層實現(xiàn)細(xì)節(jié),為了支持多種復(fù)雜業(yè)務(wù)對事務(wù)的精細(xì)控制,spring提供了事務(wù)的傳播屬性,結(jié)合聲明式事務(wù),成就了一大事務(wù)利器。

 

spring事務(wù)傳播屬性示例分析

 

在TransactionDefinition類中,spring提供了6種傳播屬性,接下來分別用簡單示例來說明。

溫馨提醒:下文提到的加入當(dāng)前事務(wù),指的是底層使用同一個Connection,但是事務(wù)狀態(tài)對象是可以重新創(chuàng)建的,并不影響。文章提到的當(dāng)前只存在一個事務(wù),表示的是共用底層的一個Connection,而不在乎創(chuàng)建了多少個事務(wù)狀態(tài)對象(TransactionStatus)。

 

1、PROPAGATION_REQUIRED

說明: 如果當(dāng)前已經(jīng)存在事務(wù),那么加入該事務(wù),如果不存在事務(wù),創(chuàng)建一個事務(wù),這是默認(rèn)的傳播屬性值。

看一個小例子,代碼如下:

?
1
2
3
4
5
6
7
8
9
10
@Transactional
public void service(){
 serviceA();
 serviceB();
}
 
@Transactional
serviceA();
@Transactional
serviceB();

serviceA 和 serviceB 都聲明了事務(wù),默認(rèn)情況下,propagation=PROPAGATION_REQUIRED,整個service調(diào)用過程中,只存在一個共享的事務(wù),當(dāng)有任何異常發(fā)生的時候,所有操作回滾。

 

2、PROPAGATION_SUPPORTS

說明:如果當(dāng)前已經(jīng)存在事務(wù),那么加入該事務(wù),否則創(chuàng)建一個所謂的空事務(wù)(可以認(rèn)為無事務(wù)執(zhí)行)。

看一個小例子,代碼如下:

?
1
2
3
4
5
6
7
public void service(){
  serviceA();
  throw new RunTimeException();
}
 
@Transactional(propagation=Propagation.SUPPORTS)
serviceA();

serviceA執(zhí)行時當(dāng)前沒有事務(wù),所以service中拋出的異常不會導(dǎo)致 serviceA回滾。

再看一個小例子,代碼如下:

?
1
2
3
4
5
6
7
8
9
10
public void service(){
  serviceA();
}
 
@Transactional(propagation=Propagation.SUPPORTS)
serviceA(){
 do sql 1
 1/0;
 do sql 2
}

由于serviceA運行時沒有事務(wù),這時候,如果底層數(shù)據(jù)源defaultAutoCommit=true,那么sql1是生效的,如果defaultAutoCommit=false,那么sql1無效,如果service有@Transactional標(biāo)簽,serviceA共用service的事務(wù)(不再依賴defaultAutoCommit),此時,serviceA全部被回滾。

 

3、 PROPAGATION_MANDATORY

說明:當(dāng)前必須存在一個事務(wù),否則拋出異常。

看一個小例子,代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
public void service(){
  serviceB();
  serviceA();
}
serviceB(){
 do sql
}
@Transactional(propagation=Propagation.MANDATORY)
serviceA(){
 do sql
}

這種情況執(zhí)行 service會拋出異常,如果defaultAutoCommit=true,則serviceB是不會回滾的,defaultAutoCommit=false,則serviceB執(zhí)行無效。

 

4、PROPAGATN_REQUIRES_NEW

說明:如果當(dāng)前存在事務(wù),先把當(dāng)前事務(wù)相關(guān)內(nèi)容封裝到一個實體,然后重新創(chuàng)建一個新事務(wù),接受這個實體為參數(shù),用于事務(wù)的恢復(fù)。更直白的說法就是暫停當(dāng)前事務(wù)(當(dāng)前無事務(wù)則不需要),創(chuàng)建一個新事務(wù)。 針對這種情況,兩個事務(wù)沒有依賴關(guān)系,可以實現(xiàn)新事務(wù)回滾了,但外部事務(wù)繼續(xù)執(zhí)行。

看一個小例子,代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Transactional
public void service(){
 serviceB();
 try{
  serviceA();
 }catch(Exception e){
 }
}
serviceB(){
 do sql
}
@Transactional(propagation=Propagation.REQUIRES_NEW)
serviceA(){
 do sql 1
 1/0;
 do sql 2
}

當(dāng)調(diào)用service接口時,由于serviceA使用的是REQUIRES_NEW,它會創(chuàng)建一個新的事務(wù),但由于serviceA拋出了運行時異常,導(dǎo)致serviceA整個被回滾了,而在service方法中,捕獲了異常,所以serviceB是正常提交的。 注意,service中的try … catch 代碼是必須的,否則service也會拋出異常,導(dǎo)致serviceB也被回滾。

 

5、Propagation.NOT_SUPPORTED

說明:如果當(dāng)前存在事務(wù),掛起當(dāng)前事務(wù),然后新的方法在沒有事務(wù)的環(huán)境中執(zhí)行,沒有spring事務(wù)的環(huán)境下,sql的提交完全依賴于 defaultAutoCommit屬性值 。

看一個小例子,代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Transactional
public void service(){
  serviceB();
  serviceA();
}
serviceB(){
 do sql
}
@Transactional(propagation=Propagation.NOT_SUPPORTED)
serviceA(){
 do sql 1
 1/0;
 do sql 2
}

當(dāng)調(diào)用service方法的時候,執(zhí)行到serviceA方法中的1/0代碼時,拋出了異常,由于serviceA處于無事務(wù)環(huán)境下,所以 sql1是否生效取決于defaultAutoCommit的值,當(dāng)defaultAutoCommit=true時,sql1是生效的,但是service由于拋出了異常,所以serviceB會被回滾。

 

6、 PROPAGATION_NEVER

說明: 如果當(dāng)前存在事務(wù),則拋出異常,否則在無事務(wù)環(huán)境上執(zhí)行代碼。

看一個小例子,代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
public void service(){
 serviceB();
 serviceA();
}
serviceB(){
 do sql
}
@Transactional(propagation=Propagation.NEVER)
serviceA(){
 do sql 1
 1/0;
 do sql 2
}

上面的示例調(diào)用service后,若defaultAutoCommit=true,則serviceB方法及serviceA中的sql1都會生效。

 

7、 PROPAGATION_NESTED

說明: 如果當(dāng)前存在事務(wù),則使用 SavePoint 技術(shù)把當(dāng)前事務(wù)狀態(tài)進行保存,然后底層共用一個連接,當(dāng)NESTED內(nèi)部出錯的時候,自行回滾到 SavePoint這個狀態(tài),只要外部捕獲到了異常,就可以繼續(xù)進行外部的事務(wù)提交,而不會受到內(nèi)嵌業(yè)務(wù)的干擾,但是,如果外部事務(wù)拋出了異常,整個大事務(wù)都會回滾。

注意: spring配置事務(wù)管理器要主動指定 nestedTransactionAllowed=true,如下所示:

?
1
2
3
4
5
<bean id="dataTransactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
 <property name="dataSource" ref="dataDataSource" />
 <property name="nestedTransactionAllowed" value="true" />
</bean>

看一個小例子,代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Transactional
public void service(){
 serviceA();
 try{
  serviceB();
 }catch(Exception e){
 }
}
serviceA(){
 do sql
}
@Transactional(propagation=Propagation.NESTED)
serviceB(){
 do sql1
 1/0;
 do sql2
}

serviceB是一個內(nèi)嵌的業(yè)務(wù),內(nèi)部拋出了運行時異常,所以serviceB整個被回滾了,由于service捕獲了異常,所以serviceA是可以正常提交的。

再來看一個例子,代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
@Transactional
public void service(){
  serviceA();
  serviceB();
  1/0;
}
@Transactional(propagation=Propagation.NESTED)
serviceA(){
 do sql
}
serviceB(){
 do sql
}

由于service拋出了異常,所以會導(dǎo)致整個service方法被回滾。(這就是跟PROPAGATION_REQUIRES_NEW不一樣的地方了,NESTED方式下的內(nèi)嵌業(yè)務(wù)會受到外部事務(wù)的異常而回滾。)

 

實現(xiàn)淺析

 

前面舉例說明了spring事務(wù)提供的幾種傳播屬性,用于滿足多種不同的業(yè)務(wù)需求,大家可以依業(yè)務(wù)而定。接著我們再來看看spring實現(xiàn)這些傳播屬性最重要的技術(shù)依賴是什么。本小節(jié)列舉 PROPAGATION_REQUIRES_NEW 和 Propagation.NESTED 分別進行簡要說明。

 

1、 PROPAGATION_REQUIRES_NEW 實現(xiàn)原理

如下的代碼調(diào)用:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Transactional
public void service(){
 serviceB();
 try{
  serviceA();
 }catch(Exception e){
 }
}
 
@Transactional(propagation=Propagation.REQUIRES_NEW)
serviceA(){
 do sql 1
 1/0;
 do sql 2
}
serviceB(){
 do sql
}

執(zhí)行原理圖如下:

spring事務(wù)Propagation及其實現(xiàn)原理詳解

a. 創(chuàng)建事務(wù)狀態(tài)對象,獲取一個新的連接,重置連接的 autoCommit,fetchSize,timeout等屬性

b. 把連接綁定到ThreadLocal變量

c. 掛起當(dāng)前事務(wù),把當(dāng)前事務(wù)狀態(tài)對象,連接等信息封裝成一SuspendedResources對象,可用于恢復(fù)

d. 創(chuàng)建新的事務(wù)狀態(tài)對象,重新獲取新的連接,重置新連接的 autoCommit,fetchSize,timeout等屬性,同時,保存SuspendedResources對象,用于事務(wù)的恢復(fù),把新的連接綁定到ThreadLocal變量(覆蓋操作)

e. 捕獲到異常,回滾ThreadLocal中的連接,恢復(fù)連接參數(shù),關(guān)閉連接,恢復(fù)SuspendedResources

f. 提交ThreadLocal變量中的連接(導(dǎo)致serviceB被提交),還原連接參數(shù),關(guān)閉連接,連接歸還數(shù)據(jù)源

所以程序執(zhí)行的結(jié)果就是 serviceA被回滾了,serviceB成功提交了。

 

2、 PROPAGATION_NESTED 實現(xiàn)原理

如下的代碼調(diào)用:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Transactional
public void service(){
 serviceA();
 try{
   serviceB();
 }catch(Exception e){
 }
}
serviceA(){
 do sql
}
@Transactional(propagation=Propagation.NESTED)
serviceB(){
 do sql1
 1/0;
 do sql2
}

執(zhí)行原理圖如下:

spring事務(wù)Propagation及其實現(xiàn)原理詳解

a. 創(chuàng)建事務(wù)狀態(tài)對象,獲取一個新的連接,重置連接的 autoCommit,fetchSize,timeout等屬性

b. 把連接綁定到ThreadLocal變量

c. 標(biāo)記使用當(dāng)前事務(wù)狀態(tài)對象,獲取ThreadLocal連接對象,保存當(dāng)前連接的SavePoint,用于異常恢復(fù),此時的SavePoint就是執(zhí)行完serviceA后的狀態(tài)

d. 捕獲到異常,使用c中的SavePoint進行事務(wù)回滾,也就是把狀態(tài)回滾到執(zhí)行serviceA后的狀態(tài),serviceB方法所有執(zhí)行不生效

e. 獲取ThreadLocal中的連接對象,提交事務(wù),恢復(fù)連接屬性,關(guān)閉連接

 

其它

 

spring在底層數(shù)據(jù)源的基礎(chǔ)上,利用 ThreadLocal,SavePoint等技術(shù)點實現(xiàn)了多種事務(wù)傳播屬性,便于實現(xiàn)各種復(fù)雜的業(yè)務(wù)。只有理解了傳播屬性的原理才能更好的駕馭spring事務(wù)。Spring回滾事務(wù)依賴于對異常的捕獲,默認(rèn)情況下,只有拋出RuntimeException和Error才會回滾事務(wù),當(dāng)然可以進行配置,更多信息可以查看 @Transactional 這個注解。

 

總結(jié)

 

spring的聲明式事務(wù)給我們帶來了極大的便利,為了用好這把利器,理解底層的原理還是有必要的,本篇只是spring事務(wù)的冰山一角,讀者可以在此基礎(chǔ)上自行深入探索。

以上就是本文關(guān)于spring事務(wù)Propagation及其實現(xiàn)原理詳解的全部內(nèi)容,希望對大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站其他相關(guān)專題,如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!

原文鏈接:http://blog.csdn.net/yanyan19880509/article/details/53041564

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 欧美大片免费高清观看 | 中文字幕在线视频一区 | 福利视频网址导航 | 成人爽a毛片一区二区免费 久久久久亚洲精品 | 成人在线免费 | 久久久久久久久久久久一区二区 | 丁香综合 | 国产一区二区三区 | 精品一区二区久久久久久久网站 | 一本大道伊人久久综合 | 91精品国产综合久久福利 | 国产一区久久 | 美日韩一区二区 | 黄频免费在线观看 | 国产成人精品网站 | 久久久国色 | 欧美欧美欧美 | 国产毛片欧美毛片久久久 | 欧美成人福利 | 日韩精品一区二区三区精品av | av网站免费看 | 成人免费在线观看 | 国产精品美女久久久久久免费 | 最近最新mv字幕免费观看 | 在线a电影 | 亚洲国产中文字幕在线 | 日韩毛片 | 亚洲国产精品久久久久久6q | 午夜视频福利在线观看 | 一级a性色生活片久久毛片 国产精品久久久久久久久久免费看 | 欧美国产视频 | 欧美精品亚洲精品 | 成人精品视频99在线观看免费 | 中文字幕亚洲一区二区va在线 | 久久精品视频免费观看 | 国产亚洲精品美女久久久久久久久久 | 欧美视频免费 | 成人国产精品视频 | 一级黄色毛片 | 久久视频国产 | 日本三级网 |