Spring在TransactionDefinition接口中規定了7種類型的事務傳播行爲。事務傳播行爲是Spring框架獨有的事務加強特性,他不屬於的事務實際提供方數據庫行爲。這是Spring爲咱們提供的強大的工具箱,使用事務傳播行能夠爲咱們的開發工做提供許多便利。可是人們對他的誤解也頗多,你必定也聽過「service方法事務最好不要嵌套」的傳言。要想正確的使用工具首先須要瞭解工具。html
事務傳播行爲用來描述由某一個事務傳播行爲修飾的方法被嵌套進另外一個方法的時事務如何傳播。spring
用僞代碼說明:數據庫
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決定,這就是事務的傳播行爲。segmentfault
事務傳播行爲類型 | 說明 |
---|---|
PROPAGATION_REQUIRED | 若是當前沒有事務,就新建一個事務,若是已經存在一個事務中,加入到這個事務中。這是最多見的選擇。 |
PROPAGATION_SUPPORTS | 支持當前事務,若是當前沒有事務,就以非事務方式執行。 |
PROPAGATION_MANDATORY | 使用當前的事務,若是當前沒有事務,就拋出異常。 |
PROPAGATION_REQUIRES_NEW | 新建事務,若是當前存在事務,把當前事務掛起。 |
PROPAGATION_NOT_SUPPORTED | 以非事務方式執行操做,若是當前存在事務,就把當前事務掛起。 |
PROPAGATION_NEVER | 以非事務方式執行,若是當前存在事務,則拋出異常。 |
PROPAGATION_NESTED | 若是當前存在事務,則在嵌套事務內執行。若是當前沒有事務,則執行與PROPAGATION_REQUIRED相似的操做。 |
定義很是簡單,也很好理解,下面咱們就進入代碼測試部分,驗證咱們的理解是否正確。app
第一種狀況。內部均爲 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 }
張三,李四插入均失敗。ide
第二種狀況。內部一種爲 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_NEWspa
跟咱們現象的是同樣的,若是哪一個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