前言
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
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/227913.html
標籤:Java
上一篇:深入淺出 Java 類加載機制!
下一篇:Elastic APM安裝
