亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

我總結(jié)的幾種@Transactional失效原因說明

 更新時(shí)間:2022年11月15日 15:53:49   作者:滕青山Y(jié)YDS  
這篇文章主要是我總結(jié)的幾種@Transactional失效原因說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

總結(jié)幾種@Transactional失效原因

非public方法

spring事務(wù)是通過動(dòng)態(tài)代理的方法來實(shí)現(xiàn)的,有兩種實(shí)現(xiàn)動(dòng)態(tài)代理的方式,jdk動(dòng)態(tài)代理方式是將目標(biāo)對(duì)象放入代理對(duì)象內(nèi)部,通過代理對(duì)象來訪問目標(biāo)對(duì)象;cglib字節(jié)碼生成是通過生成目標(biāo)對(duì)象的子類,通過重寫的方式來完成對(duì)父類的增強(qiáng)。

但是它倆實(shí)際上可以為非public方法生成代理對(duì)象,只不過spring在調(diào)用動(dòng)態(tài)代理之前,會(huì)過濾掉非public方法。如果修改spring的源碼就可以為非public方法生成代理對(duì)象了。

自調(diào)用問題

若同一類中的沒有@Transactional注解的方法內(nèi)部調(diào)用有@Transactional注解的方法,那么該事務(wù)會(huì)被忽略。

原因是Spring事務(wù)是通過Spring AOP完成的,如果從外部直接訪問使用@Transactional注解的方法,那么spring實(shí)際上會(huì)調(diào)用代理對(duì)象上的方法,在代理對(duì)象中完成事務(wù)的邏輯;

但是如果從目標(biāo)對(duì)象內(nèi)部調(diào)用了使用@Transactional注解的方法,比如在method1方法中調(diào)用了method2方法,method1沒有加@Transactional 注解,就算method2加了@Transactional 注解也沒用。因?yàn)檫@時(shí)會(huì)直接調(diào)用目標(biāo)對(duì)象中的method1方法,進(jìn)而再調(diào)用目標(biāo)對(duì)象的method2方法,并沒有走代理對(duì)象導(dǎo)致代理失效。

異常相關(guān)問題

內(nèi)部捕捉了異常,沒有拋出新的異常,導(dǎo)致事務(wù)操作不會(huì)進(jìn)行回滾:

原因是spring事務(wù)源碼中是通過有沒有出現(xiàn)異常來判斷是否回滾的。

拋出非運(yùn)行時(shí)異常

所以最好給@Transactional添加上rollbackFor=Exception.class

傳播機(jī)制配置錯(cuò)誤

錯(cuò)誤地使用傳播機(jī)制也會(huì)導(dǎo)致事務(wù)失效。如果使用了NOT_SUPPORTED和NEVER傳播機(jī)制,那么事務(wù)機(jī)會(huì)失效,如果使用了SUPPORTS傳播機(jī)制并且當(dāng)前不存在事務(wù)那么事務(wù)也會(huì)失效。

  • TransactionDefinition.PROPAGATION_SUPPORTS: 如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前沒有事務(wù),則以非事務(wù)的方式繼續(xù)運(yùn)行。
  • TransactionDefinition.PROPAGATION_NOT_SUPPORTED: 以非事務(wù)方式運(yùn)行,如果當(dāng)前存在事務(wù),則把當(dāng)前事務(wù)掛起。
  • TransactionDefinition.PROPAGATION_NEVER: 以非事務(wù)方式運(yùn)行,如果當(dāng)前存在事務(wù),則拋出異常。

@Transactional事務(wù)失效場(chǎng)景類內(nèi)部調(diào)用實(shí)測(cè)

環(huán)境springboot2.7,mysql5.7

demo1

@Component
@Order(6)
@Slf4j
public class TestRunner implements ApplicationRunner {
 
    @Autowired
    TestService testService;
 
    @Override
    public void run(ApplicationArguments args) throws Exception {
        testService.insertAndUpdate();
    }
}
@Service("testService")
public class TestServiceImpl extends ServiceImpl<TestMapper, Test> implements TestService {
 
    @Override
    public boolean updateByIdOne() {
        LambdaUpdateWrapper<Test> lambdaUpdateWrapper = new UpdateWrapper<Test>().lambda();
        lambdaUpdateWrapper.eq(Test::getId,1);
        lambdaUpdateWrapper.set(Test::getName,"test");
 
        return this.update(lambdaUpdateWrapper);
    }
 
    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public boolean insertAndUpdate() {
        boolean b = this.updateByIdOne();
 
 
        Test test = new Test();
        test.setName("2222");
 
 
        boolean save = this.save(test);
        if(b){
            throw new RuntimeException("ts");
        }
        return save;
    }
}

以上代碼先跑一遍,看看拋出異常情況,能不能回滾

看庫  毫無變化

看主鍵遞增量其實(shí)是插入過了,我覺得事務(wù)還是生效了

demo2

@Service("testService")
public class TestServiceImpl extends ServiceImpl<TestMapper, Test> implements TestService {
 
    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public boolean updateByIdOne() {
        LambdaUpdateWrapper<Test> lambdaUpdateWrapper = new UpdateWrapper<Test>().lambda();
        lambdaUpdateWrapper.eq(Test::getId,1);
        lambdaUpdateWrapper.set(Test::getName,"test");
        boolean update = this.update(lambdaUpdateWrapper);
 
        if(update){
            throw new RuntimeException("updateByIdOne");
        }
 
        LambdaUpdateWrapper<Test> lambdaUpdateWrapper2 = new UpdateWrapper<Test>().lambda();
        lambdaUpdateWrapper2.eq(Test::getId,2);
        lambdaUpdateWrapper2.set(Test::getName,"test");
        boolean update1 = this.update(lambdaUpdateWrapper2);
 
        return update;
    }
 
    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public boolean insertAndUpdate() {
 
        Test test = new Test();
        test.setName("2222");
        boolean save = this.save(test);
 
        boolean b = this.updateByIdOne();
 
        return save;
    }
}

執(zhí)行結(jié)果

子父方法都有事務(wù)注解,事務(wù)生效

demo3

@Service("testService")
public class TestServiceImpl extends ServiceImpl<TestMapper, Test> implements TestService {
 
    @Override
    public boolean updateByIdOne() {
        LambdaUpdateWrapper<Test> lambdaUpdateWrapper = new UpdateWrapper<Test>().lambda();
        lambdaUpdateWrapper.eq(Test::getId,1);
        lambdaUpdateWrapper.set(Test::getName,"test");
        boolean update = this.update(lambdaUpdateWrapper);
 
        if(update){
            throw new RuntimeException("updateByIdOne");
        }
 
        return update;
    }
    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public boolean insertAndUpdate() {
 
        Test test = new Test();
        test.setName("2222");
        boolean save = this.save(test);
 
 
        boolean b = this.updateByIdOne();
        return b;
    }
}

insertAndUpdate插入成功后又回滾,update 更新成功也回滾,事務(wù)生效

demo4

@Service("testService")
public class TestServiceImpl extends ServiceImpl<TestMapper, Test> implements TestService {
 
    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public boolean updateByIdOne() {
        LambdaUpdateWrapper<Test> lambdaUpdateWrapper = new UpdateWrapper<Test>().lambda();
        lambdaUpdateWrapper.eq(Test::getId,1);
        lambdaUpdateWrapper.set(Test::getName,"test");
        boolean update = this.update(lambdaUpdateWrapper);
 
        if(update){
            throw new RuntimeException("updateByIdOne");
        }
 
        LambdaUpdateWrapper<Test> lambdaUpdateWrapper2 = new UpdateWrapper<Test>().lambda();
        lambdaUpdateWrapper2.eq(Test::getId,2);
        lambdaUpdateWrapper2.set(Test::getName,"test");
        boolean update1 = this.update(lambdaUpdateWrapper2);
 
        return update;
    }
 
    @Override
    public boolean insertAndUpdate() {
        boolean b = this.updateByIdOne();
 
        return b;
    }
}

以上代碼一跑,結(jié)果就很清楚了。

1、在同類中調(diào)用,二個(gè)方法都有加上事務(wù)注解,生效

2、同類中,子方法有事務(wù)注解,父類方法無事務(wù)注解,在controller層調(diào)用父類方法,子方法事務(wù)不生效

3、同類中,子方法無事務(wù)注解,父類方法有事務(wù)注解,在controller層調(diào)用父類方法,之方法事務(wù)生效

這些僅為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • springboot2如何集成ElasticSearch6.4.3

    springboot2如何集成ElasticSearch6.4.3

    這篇文章主要介紹了springboot2如何集成ElasticSearch6.4.3問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • JavaWeb實(shí)現(xiàn)裁剪圖片上傳完整代碼

    JavaWeb實(shí)現(xiàn)裁剪圖片上傳完整代碼

    這篇文章主要為大家詳細(xì)介紹了javaWeb實(shí)現(xiàn)裁剪圖片上傳完整代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-09-09
  • Java 中的 Unsafe 魔法類的作用大全

    Java 中的 Unsafe 魔法類的作用大全

    Unsafe是位于sun.misc包下的一個(gè)類,主要提供一些用于執(zhí)行低級(jí)別、不安全操作的方法,關(guān)于Java 中的 Unsafe 魔法類,到底有啥用處,你都了解嗎,下面通過本文給大家普及一下
    2021-06-06
  • Java基于PDFbox實(shí)現(xiàn)讀取處理PDF文件

    Java基于PDFbox實(shí)現(xiàn)讀取處理PDF文件

    PDFbox是一個(gè)開源的、基于Java的、支持PDF文檔生成的工具庫,它可以用于創(chuàng)建新的PDF文檔,修改現(xiàn)有的PDF文檔,還可以從PDF文檔中提取所需的內(nèi)容。本文將具體介紹一下PDFbox讀取處理PDF文件的示例代碼,感興趣的可以學(xué)習(xí)一下
    2022-02-02
  • 深入分析JAVA Vector和Stack的具體用法

    深入分析JAVA Vector和Stack的具體用法

    這篇文章主要介紹了深入分析JAVA Vector和Stack的具體用法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-12-12
  • Java實(shí)現(xiàn)簡單的迷宮游戲詳解

    Java實(shí)現(xiàn)簡單的迷宮游戲詳解

    迷宮游戲作為經(jīng)典的小游戲,一直深受大家的喜愛。本文小編將為大家詳細(xì)介紹一下如何用Java實(shí)現(xiàn)一個(gè)簡單的迷宮小游戲,感興趣的可以動(dòng)手試一試
    2022-02-02
  • SpringBoot MyBatis保姆級(jí)整合教程

    SpringBoot MyBatis保姆級(jí)整合教程

    因?yàn)镾pring Boot框架開發(fā)的便利性,所以實(shí)現(xiàn)Spring Boot與數(shù)據(jù)訪問層框架(例如MyBatis)的整合非常簡單,主要是引入對(duì)應(yīng)的依賴啟動(dòng)器,并進(jìn)行數(shù)據(jù)庫相關(guān)參數(shù)設(shè)置即可
    2022-06-06
  • SpringBoot整合sharding-jdbc實(shí)現(xiàn)自定義分庫分表的實(shí)踐

    SpringBoot整合sharding-jdbc實(shí)現(xiàn)自定義分庫分表的實(shí)踐

    本文主要介紹了SpringBoot整合sharding-jdbc實(shí)現(xiàn)自定義分庫分表的實(shí)踐,將通過自定義算法來實(shí)現(xiàn)定制化的分庫分表來擴(kuò)展相應(yīng)業(yè)務(wù),感興趣的可以了解一下
    2021-11-11
  • Java內(nèi)存區(qū)域與內(nèi)存溢出異常詳解

    Java內(nèi)存區(qū)域與內(nèi)存溢出異常詳解

    這篇文章主要介紹了Java內(nèi)存區(qū)域與內(nèi)存溢出異常詳解的相關(guān)資料,需要的朋友可以參考下
    2017-03-03
  • JAVA 根據(jù)設(shè)置的概率生成隨機(jī)數(shù)的方法

    JAVA 根據(jù)設(shè)置的概率生成隨機(jī)數(shù)的方法

    本篇文章主要介紹了JAVA 根據(jù)設(shè)置的概率生成隨機(jī)數(shù)的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-08-08

最新評(píng)論