自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Spring雙層事務(wù),我拋出的異常去哪了?

開(kāi)發(fā) 后端
系統(tǒng) A 調(diào)用系統(tǒng) B 執(zhí)行數(shù)據(jù)同步,系統(tǒng) B 返回了錯(cuò)誤提示,系統(tǒng) A 需要將前邊保存的回滾掉,同時(shí)把錯(cuò)誤信息向上拋。

[[375634]]

系統(tǒng) A 調(diào)用系統(tǒng) B 執(zhí)行數(shù)據(jù)同步,系統(tǒng) B 返回了錯(cuò)誤提示,系統(tǒng) A 需要將前邊保存的回滾掉,同時(shí)把錯(cuò)誤信息向上拋。

大致代碼如下 

  1. @Service("noteService")  
  2. public class NoteServiceImpl implements NoteService {  
  3.     @Resource  
  4.     private SearchService searchService;  
  5.     @Transactional(rollbackFor = Throwable.class)  
  6.     @Override  
  7.     public CommonResponse<NoteEntity> save(NoteEntity note) {  
  8.         // 一系列 DB 操作  
  9.         try {  
  10.             searchService.sync(note);  
  11.         } catch (Exception e) {  
  12.             e.printStackTrace();  
  13.         }  
  14.         return CommonResponse.success(entity);  
  15.     }  
  16.  
  17. @Service("searchService")  
  18. public class SearchServiceImpl implements SearchService {  
  19.     @Transactional(rollbackFor = Throwable.class)  
  20.     @Override  
  21.     public void sync(NoteEntity note) {  
  22.         // 一系列 DB 操作  
  23.         throw new RuntimeException("同步異常! [XXX]"); 
  24.     }  
  25.  
  26. @SpringBootTest  
  27. public class NoteTests {  
  28.     @Resource  
  29.     private NoteService noteService;  
  30.     @Test  
  31.     public void saveNote() {  
  32.         NoteEntity entity = new NoteEntity();  
  33.         entity.setTitle("念奴嬌赤壁懷古");  
  34.         entity.setContent("大江東去,浪淘盡,千古風(fēng)流人物。故壘西邊,人道是:三國(guó)周郎赤壁。。。");  
  35.         entity.setTags("蘇軾,宋代");  
  36.         entity.setCategory("蘇軾詩(shī)詞");  
  37.         try {  
  38.             noteService.save(entity);  
  39.         } catch (Exception e) {  
  40.             e.printStackTrace(); 
  41.              // FIXME 我想在這里拿到的是 同步異常! [XXX]  
  42.             // FIXME 但是這里拿到的是 Transaction silently rolled back because it has been marked as rollback-only  
  43.             System.out.println(">>>>>>>>>> " + e.getMessage());  
  44.         }  
  45.     }  

事出有因

代碼歷史久遠(yuǎn),為何這樣寫(xiě)已無(wú)從追溯。

納悶了一會(huì)兒,看到雙層事務(wù),就想起了 Spring事務(wù)傳播機(jī)制,前邊理解得比較膚淺。Spring 系列面試題和答案我全部整理好了,請(qǐng)關(guān)注公眾號(hào)Java技術(shù)棧,回復(fù):面試。

沒(méi)有特殊的配置,自然是走默認(rèn)的事務(wù)傳播機(jī)制了,也就是 Propagation.REQUIRED。

國(guó)際慣例,列出事務(wù)傳播機(jī)制: 

  1. 1、PROPAGATION_REQUIRED 
  2. 當(dāng)前沒(méi)事務(wù),則創(chuàng)建事務(wù);存在事務(wù),就加入該事務(wù),這是最常用的設(shè)置。  
  3. 2、PROPAGATION_SUPPORTS  
  4. 當(dāng)前存在事務(wù),就加入事務(wù),當(dāng)前不存在事務(wù),就以非事務(wù)方式執(zhí)行。 
  5. 3、PROPAGATION_MANDATORY  
  6. 當(dāng)前存在事務(wù),就加入事務(wù);當(dāng)前不存在事務(wù),就拋出異常。  
  7. 4、PROPAGATION_REQUIRES_NEW  
  8. 無(wú)條件創(chuàng)建新事務(wù)。  
  9. 5、PROPAGATION_NOT_SUPPORTED  
  10. 以非事務(wù)方式執(zhí)行,如果當(dāng)前存在事務(wù),就將當(dāng)前事務(wù)掛起。  
  11. 6、PROPAGATION_NEVER  
  12. 以非事務(wù)方式運(yùn)行,如果存在事務(wù),就拋出異常。 
  13. 7、PROPAGATION_NESTED  
  14. 開(kāi)始執(zhí)行事務(wù)前,先保存一個(gè)savepoint,當(dāng)發(fā)生異常時(shí),就回滾到savepoint;沒(méi)有異常時(shí),跟著外部事務(wù)一起提交或回滾。 

具體原因

1、看了上邊的事務(wù)傳播機(jī)制,繼續(xù)細(xì)化問(wèn)題,內(nèi)外層共用一個(gè)事務(wù),內(nèi)層拋出異常,會(huì)導(dǎo)致整個(gè)事務(wù)失敗。

2、繼續(xù)分析,外層邏輯進(jìn)行了 try catch,就導(dǎo)致內(nèi)層的異常無(wú)法繼續(xù)向上拋出,外層事務(wù)會(huì)繼續(xù)提交。

3、事務(wù)提交時(shí),進(jìn)行事務(wù)狀態(tài)的判斷,就發(fā)現(xiàn)這個(gè)事務(wù)是失敗的,需要回滾,所以?huà)伋隽?Transaction silently rolled back because it has been marked as rollback-only 的異常。

另外,大家想學(xué) Spring Boot 的看下這個(gè)倉(cāng)庫(kù),太全了。

https://github.com/javastacks/spring-boot-best-practice

怎么解決?

銀彈自然是沒(méi)有的,根據(jù)業(yè)務(wù)場(chǎng)景選擇合適的方案。

1、當(dāng)前這種場(chǎng)景,直接把外層邏輯中的 try catch 去掉即可。異常直接向上拋,事務(wù)就不會(huì)繼續(xù)提交,調(diào)用方拿到的就是一手的異常;

2、如果內(nèi)層不是核心邏輯,記錄個(gè)日志啥的,可以把內(nèi)層事務(wù)配置為 @Transactional(rollbackFor = Throwable.class, propagation = Propagation.REQUIRES_NEW), 無(wú)論如何,都創(chuàng)建新的事務(wù),外層事務(wù)不受內(nèi)層事務(wù)影響。但是有個(gè)問(wèn)題,外層事務(wù)失敗了,內(nèi)層事務(wù)還是把記錄入庫(kù)了,有可能產(chǎn)生臟數(shù)據(jù);

3、如果外層事務(wù)失敗了,內(nèi)層事務(wù)也不能提交,那就可以使用 @Transactional(rollbackFor = Throwable.class, propagation = Propagation.NESTED)。注意:hibernate/jpa 不支持嵌套事務(wù) NESTED,可用 JdbcTemplate 代替。 

 

責(zé)任編輯:龐桂玉 來(lái)源: Java技術(shù)棧
相關(guān)推薦

2010-02-01 15:01:34

C++拋出異常

2022-07-05 14:19:30

Spring接口CGLIB

2009-03-18 08:59:28

throw異常Java

2021-09-04 07:56:44

Spring事務(wù)失效

2012-05-29 16:25:45

Transaction

2025-01-09 12:01:53

2021-02-05 11:54:09

Bug漏洞代碼

2023-10-12 10:04:03

Java代碼

2024-11-07 11:04:55

2020-10-19 11:05:17

SpringTransaction事務(wù)

2024-12-17 16:44:22

Spring開(kāi)發(fā)

2023-10-30 07:36:19

Spring事務(wù)傳播機(jī)制

2024-01-15 08:28:31

Spring事件

2019-08-23 09:20:35

Spring 5編程Java

2020-02-06 11:30:08

代碼JavaScript&&

2013-07-17 14:13:08

產(chǎn)品產(chǎn)品失敗

2010-07-02 14:34:35

SQL Server

2010-05-05 09:05:07

checked異常

2018-05-21 11:02:24

Docker硬盤(pán)空間

2020-08-19 09:45:29

Spring數(shù)據(jù)庫(kù)代碼
點(diǎn)贊
收藏

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