日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

事务传播行为的失效(异常传递)

發(fā)布時間:2023/12/20 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 事务传播行为的失效(异常传递) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

眾所周知,事務(wù)的傳播行為一共有7種,7種傳播行為具體有什么特征在這里不再贅述,詳情參考https://zhuanlan.zhihu.com/p/256263914,本文主要對對于傳播行為失效進(jìn)行探究,旨在對于事務(wù)的使用時對于細(xì)節(jié)的把控。

在這里引出第一個問題:

1.為什么我用 @Transactional(propagation = Propagation.REQUIRES_NEW)卻得到了意想不到的結(jié)果?

首先,由于spring中的事務(wù)底層采用的是jdk或cglib的動態(tài)代理,因此,不能在一個類中一個方法直接調(diào)用另一個方法,可以采用動態(tài)代理上下文的方式,在一個類中調(diào)用另一個采用事務(wù)的方法,具體參考https://blog.csdn.net/xlgen157387/article/details/79026285,亦或者在當(dāng)前類中注入當(dāng)前類的對象,采用對象的方式調(diào)用。以下采用兩個類的方式進(jìn)行調(diào)用。

代碼如下:

@Servicepublic class TestTransactional {@Autowiredprivate CustomerMapper customerMapper;@Autowiredprivate TestTransactional2 testTransactional2;@Transactional(propagation = Propagation.REQUIRED)public void methodA() {System.out.println("pre");Customer customer = new Customer();customer.setAddress("zzzzzzzz");customer.setNickname("zzzzzzzz");customer.setUsername("zzzzzzzz");customer.setPassword("zzzzzzzz");customerMapper.insert(customer);testTransactional2.methodB(65);System.out.println("post");}} @Service public class TestTransactional2 {@Autowiredprivate CustomerMapper customerMapper;@Transactional(propagation = Propagation.REQUIRES_NEW)public void methodB(Integer id) {customerMapper.deleteById(id);throw new RuntimeException();} }

methodA中事務(wù)采用Propagation.REQUIRED,在methodA調(diào)用methodB,methodB的事務(wù)傳播行為為Propagation.REQUIRES_NEW,按照Propagation.REQUIRES_NEW的特征,方法B會開啟一個新的事務(wù),方法A的事務(wù)會被掛起,如果方法B發(fā)生異常,方法B回滾,但是方法A不回滾,但是當(dāng)方法B發(fā)生異常時,方法A也進(jìn)行了回滾。如下:

可以發(fā)現(xiàn)65條數(shù)據(jù)沒有刪除,也沒有添加新的數(shù)據(jù),說明方法B和方法A都發(fā)生了回滾。這是為什么呢?

這事因為,方法B執(zhí)行時拋出了異常,而方法A中并沒有進(jìn)行捕獲,造成方法A中也出現(xiàn)了異常,造成A的事務(wù)也進(jìn)行了回滾。如果在方法A中加入try{}catch{},那么問題就會迎刃而解。如下:

@Service public class TestTransactional {@Autowiredprivate CustomerMapper customerMapper;@Autowiredprivate TestTransactional2 testTransactional2;@Transactional(propagation = Propagation.REQUIRED)public void methodA() {System.out.println("pre");Customer customer = new Customer();customer.setAddress("zzzzzzzz");customer.setNickname("zzzzzzzz");customer.setUsername("zzzzzzzz");customer.setPassword("zzzzzzzz");customerMapper.insert(customer);try {testTransactional2.methodB(65);} catch (Exception e) {e.printStackTrace();}System.out.println("post");}}

可以看出,方法B進(jìn)行了回滾,方法A沒有進(jìn)行回滾。

2.如果methodB的傳播采用@Transactional(propagation = Propagation.REQUIRED)時,我可以對異常進(jìn)行捕獲嗎?

但是當(dāng)方法B中事務(wù)傳播采用Propagation.REQUIRED(如果上下文中已經(jīng)存在事務(wù),那么就加入到事務(wù)中執(zhí)行,如果當(dāng)前上下文中不存在事務(wù),則新建事務(wù)執(zhí)行)時,try{}catch{}會不會影響事務(wù)的執(zhí)行呢?

@Service public class TestTransactional2 { @Autowired private CustomerMapper customerMapper;@Transactional(propagation = Propagation.REQUIRED) public void methodB(Integer id) {customerMapper.deleteById(id);throw new RuntimeException();} }

可以發(fā)現(xiàn),try{}catch{}并沒有影響Propagation.REQUIRED的特征,因為,方法B使用的事務(wù)是方法A中的事務(wù),方法A與方法B公用一個事務(wù),如果方法B發(fā)生了異常,即使方法A中進(jìn)行了捕獲,方法A也會發(fā)生回滾。所以,try{}catch{}也應(yīng)用于propagation = Propagation.REQUIRED時。

3.如果方法B中事務(wù)傳播采用Propagation.NOT_SUPPORTED時,我需要進(jìn)行異常捕獲嗎?

Propagation.NOT_SUPPORTED,當(dāng)前級別的特點就是上下文中存在事務(wù),則掛起事務(wù),執(zhí)行當(dāng)前邏輯,結(jié)束后恢復(fù)上下文的事務(wù)。

@Service public class TestTransactional {@Autowiredprivate CustomerMapper customerMapper;@Autowiredprivate TestTransactional2 testTransactional2;@Transactional(propagation = Propagation.REQUIRED)public void methodA() {System.out.println("pre");Customer customer = new Customer();customer.setAddress("zzzzzzzz");customer.setNickname("zzzzzzzz");customer.setUsername("zzzzzzzz");customer.setPassword("zzzzzzzz");customerMapper.insert(customer);testTransactional2.methodB(65);System.out.println("post");}} @Service public class TestTransactional2 {@Autowiredprivate CustomerMapper customerMapper;@Transactional(propagation = Propagation.NOT_SUPPORTED)public void methodB(Integer id) {customerMapper.deleteById(id);throw new RuntimeException();} }

當(dāng)方法A沒有進(jìn)行異常捕獲時,得到了意想不到的結(jié)果:

方法B中刪除成功,方法A進(jìn)行了回滾,按照Propagation.NOT_SUPPORTED的特性,應(yīng)該是方法B沒有事務(wù)的執(zhí)行,不會影響方法A中的事務(wù),但是,結(jié)果顯示,方法B拋出的異常影響了方法A中的事務(wù),因此,方法A中一定要進(jìn)行異常的捕獲。

4.如果方法B中事務(wù)傳播采用Propagation.NESTED時,我需要進(jìn)行異常捕獲嗎?

Propagation.NESTED,嵌套是子事務(wù)套在父事務(wù)中執(zhí)行,子事務(wù)是父事務(wù)的一部分,在進(jìn)入子事務(wù)之前,父事務(wù)建立一個回滾點,叫save point,然后執(zhí)行子事務(wù),這個子事務(wù)的執(zhí)行也算是父事務(wù)的一部分,然后子事務(wù)執(zhí)行結(jié)束,父事務(wù)繼續(xù)執(zhí)行。

如果子事務(wù)回滾,會發(fā)生什么?

父事務(wù)會回滾到進(jìn)入子事務(wù)前建立的save point,然后嘗試其他的事務(wù)或者其他的業(yè)務(wù)邏輯,父事務(wù)之前的操作不會受到影響,更不會自動回滾。

如果父事務(wù)回滾,會發(fā)生什么?

父事務(wù)回滾,子事務(wù)也會跟著回滾!為什么呢,因為父事務(wù)結(jié)束之前,子事務(wù)是不會提交的,我們說子事務(wù)是父事務(wù)的一部分,正是這個道理。那么:

@Service public class TestTransactional {@Autowiredprivate CustomerMapper customerMapper;@Autowiredprivate TestTransactional2 testTransactional2;@Transactional(propagation = Propagation.REQUIRED)public void methodA() {System.out.println("pre");Customer customer = new Customer();customer.setAddress("zzzzzzzz");customer.setNickname("zzzzzzzz");customer.setUsername("zzzzzzzz");customer.setPassword("zzzzzzzz");customerMapper.insert(customer);testTransactional2.methodB(65);System.out.println("post");}} @Service public class TestTransactional2 {@Autowiredprivate CustomerMapper customerMapper;@Transactional(propagation = Propagation.NESTED)public void methodB(Integer id) {customerMapper.deleteById(id);throw new RuntimeException();} }

當(dāng)方法A中沒有對異常進(jìn)行捕獲時,結(jié)果如下:

可以發(fā)現(xiàn),方法B和方法A都進(jìn)行了回滾,按照NESTED特性,應(yīng)該方法A不會進(jìn)行回滾而是回到了開始執(zhí)行方法B的保存的point,但是方法A進(jìn)行了回滾。當(dāng)方法A中對異常進(jìn)行捕獲時,結(jié)果就會與預(yù)期一致。

綜上所述:無論方法B中傳播行為是何種方式,方法A中都要對異常進(jìn)行捕獲,否則會發(fā)生出乎意料的結(jié)果,而且這種錯誤還很難發(fā)現(xiàn),雖然這是運(yùn)用事務(wù)時的細(xì)節(jié)問題,但是在一些項目中總是這些細(xì)節(jié)造成重大的損失,因此,在我們做項目時在邏輯嚴(yán)謹(jǐn)?shù)耐瑫r也要對一些細(xì)節(jié)進(jìn)行把握,增強(qiáng)代碼的健壯性。

總結(jié)

以上是生活随笔為你收集整理的事务传播行为的失效(异常传递)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。