欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

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

非public方法

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

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

自調(diào)用問題

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

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

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

異常相關(guān)問題

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

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

拋出非運行時異常

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

傳播機制配置錯誤

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

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

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

環(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;
    }
}

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

看庫  毫無變化

看主鍵遞增量其實是插入過了,我覺得事務(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)用,二個方法都有加上事務(wù)注解,生效

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

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

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

相關(guān)文章

  • springboot2如何集成ElasticSearch6.4.3

    springboot2如何集成ElasticSearch6.4.3

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

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

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

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

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

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

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

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

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

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

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

    SpringBoot MyBatis保姆級整合教程

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

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

    本文主要介紹了SpringBoot整合sharding-jdbc實現(xiàn)自定義分庫分表的實踐,將通過自定義算法來實現(xiàn)定制化的分庫分表來擴展相應(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è)置的概率生成隨機數(shù)的方法

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

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

最新評論