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

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

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

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

非public方法

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

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

自調(diào)用問(wèn)題

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

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

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

異常相關(guān)問(wèn)題

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

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

拋出非運(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)前沒(méi)有事務(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)景類(lèi)內(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;
    }
}

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

看庫(kù)  毫無(wú)變化

看主鍵遞增量其實(shí)是插入過(guò)了,我覺(jué)得事務(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、在同類(lèi)中調(diào)用,二個(gè)方法都有加上事務(wù)注解,生效

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

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

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

相關(guān)文章

  • springboot2如何集成ElasticSearch6.4.3

    springboot2如何集成ElasticSearch6.4.3

    這篇文章主要介紹了springboot2如何集成ElasticSearch6.4.3問(wèn)題,具有很好的參考價(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 魔法類(lèi)的作用大全

    Java 中的 Unsafe 魔法類(lèi)的作用大全

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

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

    PDFbox是一個(gè)開(kāi)源的、基于Java的、支持PDF文檔生成的工具庫(kù),它可以用于創(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的具體用法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-12-12
  • Java實(shí)現(xiàn)簡(jiǎn)單的迷宮游戲詳解

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

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

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

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

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

    本文主要介紹了SpringBoot整合sharding-jdbc實(shí)現(xiàn)自定義分庫(kù)分表的實(shí)踐,將通過(guò)自定義算法來(lái)實(shí)現(xiàn)定制化的分庫(kù)分表來(lái)擴(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ù)的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-08-08

最新評(píng)論