Spring事務的傳播屬性

前言

Spring在TransactionDefinition接口中規定了7種類型的事務傳播行為。事務傳播行為是Spring框架獨有的事務增強特性,他不屬於的事務實際提供方數據庫行為。這是Spring為我們提供的強大的工具箱,使用事務傳播行可以為我們的開發工作提供許多便利。但是人們對他的誤解也頗多,你一定也聽過“service方法事務最好不要嵌套”的傳言。要想正確的使用工具首先需要了解工具。

基礎概念

1. 什麼是事務傳播行為?

事務傳播行為用來描述由某一個事務傳播行為修飾的方法被嵌套進另一個方法的時事務如何傳播。

用偽代碼說明:

1 @Transaction(Propagation=XXX)
2  public void methodA(){
3     methodB();
4     //doSomething
5  }
6  
7  public void methodB(){
8     //doSomething
9  }

methodA中存在事務,他又調用了methodB。methodB事物的一些特性由methodA決定,這就是事務的傳播行為。

2. Spring中七種事務傳播行為

事務傳播行為類型 說明
PROPAGATION_REQUIRED 如果當前沒有事務,就新建一個事務,如果已經存在一個事務中,加入到這個事務中。這是最常見的選擇。
PROPAGATION_SUPPORTS 支持當前事務,如果當前沒有事務,就以非事務方式執行。
PROPAGATION_MANDATORY 使用當前的事務,如果當前沒有事務,就拋出異常。
PROPAGATION_REQUIRES_NEW 新建事務,如果當前存在事務,把當前事務掛起。
PROPAGATION_NOT_SUPPORTED 以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。
PROPAGATION_NEVER 以非事務方式執行,如果當前存在事務,則拋出異常。
PROPAGATION_NESTED 如果當前存在事務,則在嵌套事務內執行。如果當前沒有事務,則執行與PROPAGATION_REQUIRED類似的操作。

定義非常簡單,也很好理解,下面我們就進入代碼測試部分,驗證我們的理解是否正確。

代碼驗證

第一種情況。內部均為 propagation = Propagation.REQUIRED

 1 @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.REPEATABLE_READ)  2 @Override
 3 public void testTransactional() {
 4     int insert = downloadImgDao.test1();
 5     log.info("insert1 = {}", insert);
 6 
 7     insert = downloadImgDao.test2();
 8     log.info("insert2 = {}", insert);
 9 }
10 
11 @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.REPEATABLE_READ) 12 @Override
13 public int test1() {
14     DownloadImg downloadImg = new DownloadImg();
15     downloadImg.setId(666L);
16     downloadImg.setLink("張三");
17     downloadImg.setLinkname("16");
18     int res = downloadImgMapper.insertSelective(downloadImg);
19     log.info("res1 = {}", res);
20     return res;
21 }
22 
23 
24 @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.REPEATABLE_READ) 25 @Override
26 public int test2() {
27     DownloadImg downloadImg = new DownloadImg();
28     downloadImg.setId(888L);
29     downloadImg.setLink("李四");
30     downloadImg.setLinkname("18");
31     int res = downloadImgMapper.insertSelective(downloadImg);
32     log.info("res2 = {}", res);
33 
34     int i = 5 / 0;
35     return res;
36 }

張三,李四插入均失敗。

 

第二種情況。內部一種為 propagation = Propagation.REQUIRED,一種為Propagation.REQUIRES_NEW

 1 @Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.REPEATABLE_READ)  2 @Override
 3 public int test1() {
 4     DownloadImg downloadImg = new DownloadImg();
 5     downloadImg.setId(666L);
 6     downloadImg.setLink("張三");
 7     downloadImg.setLinkname("16");
 8     int res = downloadImgMapper.insertSelective(downloadImg);
 9     log.info("res1 = {}", res);
10     return res;
11 }
12 
13 
14 @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.REPEATABLE_READ) 15 @Override
16 public int test2() {
17     DownloadImg downloadImg = new DownloadImg();
18     downloadImg.setId(888L);
19     downloadImg.setLink("李四");
20     downloadImg.setLinkname("18");
21     int res = downloadImgMapper.insertSelective(downloadImg);
22     log.info("res2 = {}", res);
23 
24     int i = 5 / 0;
25     return res;
26 }

張三插入成功,李四插入失敗。

 

第三種情況。內部均為Propagation.REQUIRES_NEW

跟我們現象的是一樣的,如果哪個test異常,哪個就失敗,無異常的就成功。

還有一種情況是,外圍拋異常了,內部都不拋異常,兩種內部插入也都會成功。

結論

本程序是實驗了PROPAGATION_REQUIRED以及Propagation.REQUIRES_NEW。

事務默認以PROPAGATION_REQUIRED來隔離。

1: 如果內部是PROPAGATION_REQUIRED隔離級別,內部只要一個方法出錯,那麼整個事務都會回滾。

2: 如果內部有方法以Propagation.REQUIRES_NEW來隔離。那麼他會創建一個新的事務來運行,如果他拋異常了,並不會影響其他事務的以及外部的事務。

 

spring事務官方文檔:https://docs.spring.io/spring/docs/5.2.6.RELEASE/spring-framework-reference/data-access.html#tx-propagation

參考文檔:https://segmentfault.com/a/1190000013341344

 

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

※教你寫出一流的銷售文案?

※超省錢租車方案

※回頭車貨運收費標準