偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

What?天天用Spring你竟然不知道事務(wù)的傳播性?

開發(fā) 架構(gòu)
在我們?nèi)粘5拈_發(fā)中Spring是必備的技能,在面試的時(shí)候,這一塊的知識(shí)也會(huì)著重地問,雖然每天都在使用,但是稍不注意就會(huì)出問題,今天這篇文章我們來詳細(xì)的聊聊Spring的事務(wù)傳播性,助力金三銀四面試季。

[[410717]]

本文轉(zhuǎn)載自微信公眾號(hào)「故里學(xué)Java」,作者故里。轉(zhuǎn)載本文請(qǐng)聯(lián)系故里學(xué)Java公眾號(hào)。

在我們?nèi)粘5拈_發(fā)中Spring是必備的技能,在面試的時(shí)候,這一塊的知識(shí)也會(huì)著重地問,雖然每天都在使用,但是稍不注意就會(huì)出問題,今天這篇文章我們來詳細(xì)的聊聊Spring的事務(wù)傳播性,助力金三銀四面試季。

什么是Spring事務(wù)傳播性?Spring事務(wù)傳播性是當(dāng)多個(gè)包含事務(wù)的方法嵌套調(diào)用的時(shí)候,處理事務(wù)的規(guī)則。例如:兩個(gè)事務(wù)方法A、B,當(dāng)方法A調(diào)用方法B的時(shí)候,方法B是合并到方法A的事務(wù)中還是開啟一個(gè)新的事務(wù)。如果是合并到方法A的事務(wù)中,那么當(dāng)方法B回滾之后,方法A會(huì)不會(huì)回滾等等。Spring有幾種處理這種嵌套事務(wù)的方式?通過源碼我們發(fā)現(xiàn)有7種,定義在Propagation這個(gè)枚舉類中,接下來我們講詳細(xì)說一下每一種傳播行為都可以幫助我們處理什么樣的問題。

1、Propagation.REQUIRED

這種傳播行為是Spring默認(rèn)的,當(dāng)我們使用@Transactional注解且不指定傳播行為的時(shí)候就是使用這個(gè),它指的是外層的調(diào)用方法如果開啟了事務(wù),那么當(dāng)前方法就合并到外層的事務(wù)中執(zhí)行,如果外層調(diào)用方法沒有開啟事務(wù),就開啟一個(gè)事務(wù)執(zhí)行當(dāng)前方法。

  1. //服務(wù)A 
  2. @Service 
  3. public class ServiceA { 
  4.     @Autowired 
  5.     private ServiceB serviceB; 
  6.      
  7.     @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED) 
  8.     public void methodA() { 
  9.         //methodA 的業(yè)務(wù)操作 
  10.         System.out.println("methodA執(zhí)行業(yè)務(wù)"); 
  11.         //調(diào)用服務(wù)B的methodB方法 
  12.         serviceB.methodB(); 
  13.     } 
  14.  
  15. //服務(wù)B 
  16. @Service 
  17. public class ServiceB { 
  18.     @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED) 
  19.     public void methodB() { 
  20.         System.out.println("methodB執(zhí)行業(yè)務(wù)"); 
  21.     } 

我們的實(shí)例代碼,服務(wù)A的methodA方法調(diào)用了服務(wù)B的methodB方法,并且我們給methodA通過注解@Transactional加了一個(gè)事務(wù),并定義了傳播性為REQUIRED。

methodA本身開啟了事務(wù),methodB也開啟了事務(wù),且事務(wù)的傳播性為REQUIRED,所以當(dāng)methodA調(diào)用methodB的時(shí)候,methodB會(huì)合并到methodA開啟的事務(wù)中執(zhí)行。這個(gè)時(shí)候兩個(gè)方法是在一個(gè)事務(wù)中執(zhí)行的,當(dāng)兩個(gè)方法都執(zhí)行成功后提交事務(wù)。

這個(gè)地方很多人就會(huì)犯迷糊啦,如果methodB在執(zhí)行過程中拋出了異常,那么methodB會(huì)回滾,那么methodA執(zhí)行的操作會(huì)回滾嗎?這里其實(shí)只要記住一點(diǎn),這兩個(gè)操作是在同一個(gè)事務(wù)中,事務(wù)是原子性操作的,所以methodA也會(huì)回滾。

面試的時(shí)候還會(huì)進(jìn)一步挖坑!如果methodA中使用try-catch捕獲了異常,那么methodA執(zhí)行的操作還會(huì)回滾嗎?

這里還是要牢記事務(wù)本身具有原子性,所以無論有沒有catch異常,都會(huì)回滾的。

2、Propagation.SUPPORTED

這個(gè)傳播行為是說,如果當(dāng)前方法的調(diào)用方開啟了事務(wù),那么當(dāng)前方法就合并到外層事務(wù)中執(zhí)行,如果外層事務(wù)沒有開啟事務(wù),那么當(dāng)前方法也不會(huì)創(chuàng)建事務(wù),就不開啟事務(wù)執(zhí)行。

  1. //服務(wù)A 
  2. @Service 
  3. public class ServiceA { 
  4.     @Autowired 
  5.     private ServiceB serviceB; 
  6.  
  7.     public void methodA() { 
  8.         //methodA 的業(yè)務(wù)操作 
  9.         System.out.println("methodA執(zhí)行業(yè)務(wù)"); 
  10.         //調(diào)用服務(wù)B的methodB方法 
  11.         serviceB.methodB(); 
  12.     } 
  13.  
  14. //服務(wù)B 
  15. @Service 
  16. public class ServiceB { 
  17.     @Transactional(rollbackFor = Exception.class, propagation = Propagation.SUPPORTED) 
  18.     public void methodB() { 
  19.         System.out.println("methodB執(zhí)行業(yè)務(wù)"); 
  20.     } 

我們看到,methodB開啟了事務(wù),傳播性為SUPPORTED,methodA沒有開啟事務(wù),那么methodA執(zhí)行的時(shí)候不會(huì)開啟事務(wù),在調(diào)用methodB的時(shí)候,由于methodB開啟了事務(wù),但傳播性為SUPPORTED,所以methodB也不會(huì)開啟事務(wù),以非事務(wù)的方式運(yùn)行。

如果methodA開啟了事務(wù),那么methodB會(huì)合并到methodA的事務(wù)中執(zhí)行。

3、Propagation.MANDATORY

這個(gè)傳播行為是指,傳播性為MANDATORY的方法只能被開啟事務(wù)的方法調(diào)用,如果調(diào)用方?jīng)]有開啟事務(wù)就會(huì)拋出異常。

  1. //服務(wù)A 
  2. @Service 
  3. public class ServiceA { 
  4.     @Autowired 
  5.     private ServiceB serviceB; 
  6.  
  7.     public void methodA() { 
  8.         //methodA 的業(yè)務(wù)操作 
  9.         System.out.println("methodA執(zhí)行業(yè)務(wù)"); 
  10.         //調(diào)用服務(wù)B的methodB方法 
  11.         serviceB.methodB(); 
  12.     } 
  13.  
  14. //服務(wù)B 
  15. @Service 
  16. public class ServiceB { 
  17.     @Transactional(rollbackFor = Exception.class, propagation = Propagation.MANDATORY) 
  18.     public void methodB() { 
  19.         System.out.println("methodB執(zhí)行業(yè)務(wù)"); 
  20.     } 

我們的示例中,methodA沒有開啟事務(wù),調(diào)用了開啟事務(wù)并且傳播性為MANDATORY的methodB,這時(shí),執(zhí)行methodA的業(yè)務(wù)操作時(shí)不開啟事務(wù),在調(diào)用服務(wù)B的methodB方法的時(shí)候,就會(huì)拋出異常:

  1. IllegalTransactionStateException( 
  2.                     "No existing transaction found for transaction marked with propagation 'mandatory'"

4、Propagation.REQUIRES_NEW

這個(gè)傳播行為是指,每次都會(huì)開啟一個(gè)新的事務(wù)來執(zhí)行當(dāng)前方法。比如調(diào)用放methodA開啟了事務(wù),在methodA中調(diào)用開啟了事務(wù)且傳播性為REQUIRES_NEW的方法methodB,那么在methodA會(huì)開啟一個(gè)事務(wù)執(zhí)行自己的業(yè)務(wù)代碼,在調(diào)用methodB的時(shí)候的時(shí)候會(huì)先掛起methodA的事務(wù),然后開啟一個(gè)新的事務(wù)執(zhí)行methodB,在methodB的事務(wù)提交后,會(huì)恢復(fù)methodA的事務(wù)繼續(xù)執(zhí)行。

  1. //服務(wù)A 
  2. @Service 
  3. public class ServiceA { 
  4.     @Autowired 
  5.     private ServiceB serviceB; 
  6.  @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED) 
  7.     public void methodA() { 
  8.         //methodA 的業(yè)務(wù)操作 
  9.         System.out.println("methodA執(zhí)行業(yè)務(wù)"); 
  10.         //調(diào)用服務(wù)B的methodB方法 
  11.         try{ 
  12.             serviceB.methodB(); 
  13.         } catch (Exception e){ 
  14.              
  15.         } 
  16.     } 
  17.  
  18. //服務(wù)B 
  19. @Service 
  20. public class ServiceB { 
  21.     @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW) 
  22.     public void methodB() { 
  23.         System.out.println("methodB執(zhí)行業(yè)務(wù)"); 
  24.     } 

我們的實(shí)例代碼中,methodA開啟了事務(wù),傳播性為REQUIRED,所以在執(zhí)行的時(shí)候,methodA會(huì)開啟一個(gè)事務(wù)A,然后執(zhí)行methodA的業(yè)務(wù),在調(diào)用methodB的時(shí)候,由于methodB開啟了事務(wù),且事務(wù)傳播性為REQUIRES_NEW,,所以這個(gè)時(shí)候就先掛起事務(wù)A,重新開啟一個(gè)事務(wù)B來執(zhí)行methodB,在methodB執(zhí)行完提交事務(wù)后,會(huì)恢復(fù)事務(wù)A的執(zhí)行,最后再提交事務(wù)A。

這個(gè)地方面試的時(shí)候可能會(huì)問到,methodB在執(zhí)行的過程中出現(xiàn)了異常整個(gè)過程會(huì)發(fā)生什么變化?

我們根據(jù)上邊的調(diào)用圖分析,在methodB執(zhí)行過程中拋出異常,事務(wù)B會(huì)回滾,如果methodA中調(diào)用methodB的時(shí)候catch住了異常,并沒有向外排除,那么methodA不會(huì)回滾,如果methodA中沒有處理異常,那么methodA也會(huì)回滾。

5、Propagation.NOT_SUPPORTED

這個(gè)傳播性就是不支持事務(wù),如果調(diào)用方開啟了事務(wù),那么在執(zhí)行的時(shí)候會(huì)先掛起調(diào)用方的事務(wù),以非事務(wù)的方式執(zhí)行當(dāng)前的業(yè)務(wù),在執(zhí)行完之后,再恢復(fù)調(diào)用方的事務(wù)繼續(xù)執(zhí)行。

  1. //服務(wù)A 
  2. @Service 
  3. public class ServiceA { 
  4.     @Autowired 
  5.     private ServiceB serviceB; 
  6.  @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED) 
  7.     public void methodA() { 
  8.         //methodA 的業(yè)務(wù)操作 
  9.         System.out.println("methodA執(zhí)行業(yè)務(wù)"); 
  10.         //調(diào)用服務(wù)B的methodB方法 
  11.         serviceB.methodB(); 
  12.     } 
  13.  
  14. //服務(wù)B 
  15. @Service 
  16. public class ServiceB { 
  17.     @Transactional(rollbackFor = Exception.class, propagation = Propagation.NOT_SUPPORTED) 
  18.     public void methodB() { 
  19.         System.out.println("methodB執(zhí)行業(yè)務(wù)"); 
  20.     } 

在我們的實(shí)例代碼中,methodA開啟了事務(wù),傳播性為REQUIRED,methodB的傳播性為NOT_SUPPORTED,在執(zhí)行的過程中,methodA會(huì)開啟一個(gè)事務(wù)A,在調(diào)用methodB的時(shí)候,會(huì)先掛起methodA的事務(wù)A,然后以非事務(wù)的方式執(zhí)行methodB的業(yè)務(wù),在methodB執(zhí)行完之后,恢復(fù)事務(wù)A,最后提交事務(wù)A。整個(gè)過程如下圖:

6、Propagation.NEVER

這個(gè)傳播性和前一種傳播性都是不支持事務(wù),但是不同的是這種傳播性是調(diào)用方如果開啟了事務(wù),那么在執(zhí)行當(dāng)前方法的時(shí)候就會(huì)拋出異常。下邊還是通過一個(gè)示例來看:

  1. //服務(wù)A 
  2. @Service 
  3. public class ServiceA { 
  4.     @Autowired 
  5.     private ServiceB serviceB; 
  6.  @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED) 
  7.     public void methodA() { 
  8.         //methodA 的業(yè)務(wù)操作 
  9.         System.out.println("methodA執(zhí)行業(yè)務(wù)"); 
  10.         //調(diào)用服務(wù)B的methodB方法 
  11.         serviceB.methodB(); 
  12.     } 
  13.  
  14. //服務(wù)B 
  15. @Service 
  16. public class ServiceB { 
  17.     @Transactional(rollbackFor = Exception.class, propagation = Propagation.NEVER) 
  18.     public void methodB() { 
  19.         System.out.println("methodB執(zhí)行業(yè)務(wù)"); 
  20.     } 

示例中我們看到,methodA開啟了事務(wù),傳播性為REQUIRED,methodB的傳播性為NEVER,那么在methodA調(diào)用methodB的時(shí)候,就會(huì)拋出如下異常:

  1. IllegalTransactionStateException( 
  2.                     "Existing transaction found for transaction marked with propagation 'never'"

7、Propagation.NESTED

這個(gè)傳播性和REQUIRED很相似,都是當(dāng)調(diào)用方?jīng)]有開啟事務(wù)時(shí),就開啟一個(gè)新的事務(wù),如果調(diào)用方開啟了事務(wù)就合并到調(diào)用方的事務(wù)中執(zhí)行,不同的地方就是NESTED這種傳播行為可以保存狀態(tài)點(diǎn),當(dāng)事務(wù)回滾的時(shí)候,可以回滾到某一個(gè)地方,從而避免了嵌套事務(wù)全部回滾的情況。

  1. //服務(wù)A 
  2. @Service 
  3. public class ServiceA { 
  4.     @Autowired 
  5.     private ServiceB serviceB; 
  6.  @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED) 
  7.     public void methodA() { 
  8.         //methodA 的業(yè)務(wù)操作 
  9.         System.out.println("methodA執(zhí)行業(yè)務(wù)"); 
  10.         // 
  11.         try{ 
  12.             serviceB.methodB(); 
  13.         }catch(Exception e) { 
  14.              
  15.         } 
  16.         //methodA在methodB之后的業(yè)務(wù)操作... 
  17.         update(); 
  18.     } 
  19.  
  20. //服務(wù)B 
  21. @Service 
  22. public class ServiceB { 
  23.     @Transactional(rollbackFor = Exception.class, propagation = Propagation.NESTED) 
  24.     public void methodB() { 
  25.         System.out.println("methodB執(zhí)行業(yè)務(wù)"); 
  26.     } 

在這個(gè)示例中,我們可以看到,在methodA執(zhí)行的時(shí)候,如果沒有開啟事務(wù),會(huì)先開啟一個(gè)事務(wù),然后執(zhí)行methodA的業(yè)務(wù)操作;在實(shí)行調(diào)用服務(wù)B的methodB的時(shí)候,由于其傳播行為NESTED,所以會(huì)創(chuàng)建一個(gè)savepoint,用于標(biāo)記methodA執(zhí)行的業(yè)務(wù)操作。

然后methodB的業(yè)務(wù)操作是在methodA的事務(wù)中進(jìn)行的,當(dāng)methodB拋出異常時(shí),methodB中的業(yè)務(wù)操作會(huì)回滾掉,methodA執(zhí)行的業(yè)務(wù)操作并不會(huì)回滾,因?yàn)樵趫?zhí)行methodB之前創(chuàng)建了savepoint,methodB只會(huì)回滾到這個(gè)savepoint點(diǎn)之前。

這個(gè)地方注意的是,methodB回滾以后,對(duì)于methodA在methodB之后的業(yè)務(wù)操作是會(huì)被提交的,并不受methodB回滾的影響。

最后

 

我們常用的事務(wù)傳播行為其實(shí)只有兩種,分別是REQUIRED和REQUIRED_NEW。其余五種傳播行為只需要了解即可,可以在面試的時(shí)候展示一下知識(shí)面。

 

責(zé)任編輯:武曉燕 來源: 故里學(xué)Java
相關(guān)推薦

2019-10-28 08:44:29

Code Review代碼團(tuán)隊(duì)

2018-10-17 09:25:22

2020-06-12 09:20:33

前端Blob字符串

2020-07-28 08:26:34

WebSocket瀏覽器

2022-07-17 06:53:24

微服務(wù)架構(gòu)

2010-08-23 09:56:09

Java性能監(jiān)控

2011-09-15 17:10:41

2009-12-10 09:37:43

2022-10-13 11:48:37

Web共享機(jī)制操作系統(tǒng)

2021-02-01 23:23:39

FiddlerCharlesWeb

2019-05-20 08:11:02

淘寶個(gè)性化推薦

2021-06-27 21:37:27

緩存雪崩穿透

2022-06-18 23:03:05

Seata分布式事務(wù)

2019-07-23 17:52:59

Spring BootJava開發(fā)

2019-07-23 15:56:56

Spring Boot部署servlet

2021-10-17 13:10:56

函數(shù)TypeScript泛型

2020-08-11 11:20:49

Linux命令使用技巧

2021-12-22 09:08:39

JSON.stringJavaScript字符串

2015-06-19 13:54:49

2021-12-29 11:38:59

JS前端沙箱
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)