最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

spring聲明式事務(wù) @Transactional 不回滾的多種情況以及解決方案

 更新時(shí)間:2021年11月18日 11:22:33   作者:ratelfu  
本文主要介紹了spring聲明式事務(wù) @Transactional 不回滾的多種情況以及解決方案,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

本文是基于springboot完成測(cè)試測(cè)試代碼地址如下:
https://github.com/Dr-Water/springboot-action/tree/master/springboot-shiro

一、 spring 事務(wù)原理

一、Spring事務(wù)原理

在使用JDBC事務(wù)操作數(shù)據(jù)庫時(shí),流程如下:

//獲取連接 
1.Connection con = DriverManager.getConnection()
//開啟事務(wù)
2.con.setAutoCommit(true/false);
3.執(zhí)行CRUD
//提交事務(wù)/回滾事務(wù) 
4. con.commit() / con.rollback();
//關(guān)閉連接
5. conn.close();

Spring本身并不提供事務(wù),而是對(duì)JDBC事務(wù)通過AOP做了封裝,隱藏了2和4的操作,簡(jiǎn)化了JDBC的應(yīng)用。

spring對(duì)JDBC事務(wù)的封裝,是通過AOP動(dòng)態(tài)代理來實(shí)現(xiàn)的,在調(diào)用目標(biāo)方法(也就是第3步)前后會(huì)通過代理類來執(zhí)行事務(wù)的開啟、提交或者回滾操作。
spring事務(wù)使用的兩個(gè)不可忽略點(diǎn):

注意關(guān)鍵詞 “動(dòng)態(tài)代理”,這意味著要生成一個(gè)代理類,那么我們就不能在一個(gè)類內(nèi)直接調(diào)用事務(wù)方法,否則無法代理,而且該事務(wù)方法必須是public,如果定義成 protected、private 或者默認(rèn)可見性,則無法調(diào)用!

問題一、@Transactional 應(yīng)該加到什么地方,如果加到Controller會(huì)回滾嗎?

@Transactional 最好加到service層,加到Controller層也是生效的,但是為了規(guī)范起見,還是加到service層上。

下載代碼并啟動(dòng)難項(xiàng)目進(jìn)行驗(yàn)證:主要代碼如下:
Controller層代碼如下:

 @Autowired
    private TransactionalService transactionalService;

    @Autowired
    private UserDao userDao;

    @Autowired
    private JwtUserDao jwtUserDao;

    /**
     * 測(cè)試@Transactional 注解加到service層事務(wù)是否回滾
     */
    @RequestMapping("/tx")
    public void serviceTX(){
        transactionalService.controllerTX();
    }
    /**
     * 測(cè)試@Transactional 注解加到Controller層事務(wù)是否回滾
     */
    @Transactional(rollbackFor = Exception.class)
    @RequestMapping("/ctx2")
    public void cTX2(){
        userDao.update();
        System.out.println(2/0);
        jwtUserDao.update();
    }

 /**
     * 測(cè)試@Transactional 注解加到Controller層事務(wù)是否回滾
     * 這里在Controller層為了方便直接調(diào)用了dao層,在實(shí)際開發(fā)中dao層即可在Controller層調(diào)用也可以在service層調(diào)用,
     * 比如service層只是直接調(diào)用dao層一個(gè)方法,此外沒有任何操作,那么這時(shí)候完全不用寫service層的方法,直接在Controller調(diào)用dao層即可,
     * 當(dāng)然如果公司有規(guī)范,必須嚴(yán)格按照mvc的模式進(jìn)行開發(fā),則另說
     */
    @Transactional(rollbackFor = Exception.class)
    @RequestMapping("/ctx2")
    public void cTX2(){
        userDao.update();
         //手動(dòng)拋出一個(gè)RuntimeException
        System.out.println(2/0);
        jwtUserDao.update();
    }

service層的主要代碼

 @Autowired
    private UserDao userDao;

    @Autowired
    private  JwtUserDao  jwtUserDao;

    @Transactional(rollbackFor = Exception.class)
    public void controllerTX(){
        userDao.update();
         //手動(dòng)拋出一個(gè)RuntimeException
        System.out.println(2/0);
        jwtUserDao.update();
    }

dao層sql語句如下:

 <update id="update">
        UPDATE jwt_user SET username ='wangwuupdate' WHERE user_id= 2
    </update>
    
 <update id="update">
        UPDATE user SET username ='zsupdate' WHERE id= 2
    </update>

數(shù)據(jù)庫原始數(shù)據(jù):

在這里插入圖片描述

在這里插入圖片描述

瀏覽器中輸入:http://localhost:8081/tx/tx,由于本次使用測(cè)試代碼進(jìn)行統(tǒng)一的異常處理所以瀏覽器的返回?cái)?shù)據(jù)如下:

在這里插入圖片描述

控制臺(tái)輸出如下:

在這里插入圖片描述

查看數(shù)據(jù)庫中的數(shù)據(jù)并沒有被修改
瀏覽器中輸入:http://localhost:8081/tx/ctx2,

在這里插入圖片描述

在這里插入圖片描述

查看數(shù)據(jù)庫中的數(shù)據(jù)并沒有被修改
由此可以得出 :@Transactional 加到Controller層也是生效的,但是為了規(guī)范起見,還是加到service層上。

問題二、 @Transactional 注解中用不用加rollbackFor = Exception.class 這個(gè)屬性值

spring的api doc中有折磨一句描述:

在這里插入圖片描述

紅框中的內(nèi)容如下:

rolling back on RuntimeException and Error but not on checked exceptions

大致意思就默認(rèn)情況下,當(dāng)程序發(fā)生 RuntimeException 和 Error 的這兩種異常的時(shí)候事務(wù)會(huì)回滾,但是如果發(fā)生了checkedExcetions ,如fileNotfundException 則不會(huì)回滾,所以 rollbackFor = Exception.class 這個(gè)一定要加!
驗(yàn)證如下:
瀏覽器輸入:http://localhost:8081/tx/ctx3
控制臺(tái)輸出如下:

在這里插入圖片描述

這時(shí)候查看數(shù)據(jù)庫中的數(shù)據(jù)并沒有被修改
瀏覽器輸入:http://localhost:8081/tx/ctx4

在這里插入圖片描述

這時(shí)候查看數(shù)據(jù)庫數(shù)據(jù)已經(jīng)被修改:

在這里插入圖片描述

在這里插入圖片描述

問題三:事務(wù)調(diào)用嵌套問題具體結(jié)果如下代碼:

/**
     * 同類中在方法a中調(diào)用b
     * a沒有事務(wù),b有 ,異常發(fā)生在b中 不會(huì)回滾
     */
    @RequestMapping("/a1")
    public void a1(){
        transactionalService.a1();
    }

    /**
     * 同類中在方法a中調(diào)用b
     * a沒有事務(wù),b有 ,異常發(fā)生在a中 不會(huì)回滾
     */
    @RequestMapping("/a2")
    public void a2(){
        transactionalService.a2();
    }
    /**
     * 同類中在方法a中調(diào)用b
     * a有事務(wù),b沒有 ,異常發(fā)生在b中 會(huì)回滾
     */
    @RequestMapping("/a3")
    public void a3(){
        transactionalService.a3();
    }
    /**
     * 同類中在方法a中調(diào)用b
     * a有事務(wù),b沒有 ,異常發(fā)生在a中 會(huì)回滾
     */
    @RequestMapping("/a4")
    public void a4(){
        transactionalService.a4();
    }
    /**
     * 同類中在方法a中調(diào)用b
     * a有事務(wù),b也有 ,異常發(fā)生在b中 會(huì)回滾
     */
    @RequestMapping("/a5")
    public void a5(){
        transactionalService.a5();
    }
    /**
     * 同類中在方法a中調(diào)用b
     * a有事務(wù),b也有 ,異常發(fā)生在a中 會(huì)回滾
     */
    @RequestMapping("/a6")
    public void a6(){
        transactionalService.a6();
    }


    /**
     *a類中調(diào)用b類中的方法
     * a中有事務(wù),b中也有 會(huì)回滾
     *
     */
    @RequestMapping("/b5")
    public  void b5(){
        transactionalService.b5();
    }

    /**
     *a類中調(diào)用b類中的方法
     * a中有事務(wù),b中沒有 會(huì)回滾
     *
     */
    @RequestMapping("/b6")
    public  void b6(){
        transactionalService.b6();
    }

    /**
     *a類中調(diào)用b類中的方法
     * a沒有事務(wù),b中有 不會(huì)回滾
     *
     */
    @RequestMapping("/b7")
    public  void b7(){
        transactionalService.b7();
    }

    /**
     *a類中調(diào)用b類中的方法
     * a沒有事務(wù),b中沒有 不會(huì)回滾
     *
     */
    @RequestMapping("/b8")
    public  void b8(){
        transactionalService.b8();
    }

總結(jié):如果在a方法中調(diào)用b方法不管是不是a和b是不是在同一個(gè)類中,只要a方法中沒有事務(wù),則發(fā)生異常的時(shí)候不會(huì)回滾,即:當(dāng)a無事務(wù)時(shí),則a和b均沒有事務(wù),當(dāng)a有事務(wù)時(shí),b如果有事務(wù),則b事務(wù)會(huì)加到a事務(wù)中,二者為同一事務(wù)!

四、總結(jié)

在springboot中默認(rèn)是開啟事務(wù)的,在service層的方法加上@Transactional(rollbackFor = Exception.class) 注解即可實(shí)現(xiàn)事務(wù) 如果在方法a中調(diào)用方法b 如果要實(shí)現(xiàn)事務(wù),則只需要在方法上加上@Transactional(rollbackFor = Exception.class) 即可!
如果業(yè)務(wù)需要,一定要拋出checked異常的話,可以通過rollbackFor屬性指定異常類型即可。有興趣的可以動(dòng)手驗(yàn)證一下,這里不再贅述。

五、 參考鏈接

Spring Boot中的事務(wù)管理
深入理解 Spring 之 SpringBoot 事務(wù)原理
聲明式事務(wù)不回滾@Transactional的避坑正確使用
Spring聲明式事務(wù)不回滾問題
spring 事務(wù)應(yīng)用誤區(qū)總結(jié):那些導(dǎo)致事務(wù)不回滾的坑
你的Spring事務(wù)為什么不會(huì)自動(dòng)回滾,包含異常的分類
Java異常之checked與unchecked

到此這篇關(guān)于spring聲明式事務(wù) @Transactional 不回滾的多種情況以及解決方案的文章就介紹到這了,更多相關(guān)spring @Transactional不回滾內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解Maven 搭建spring boot多模塊項(xiàng)目(附源碼)

    詳解Maven 搭建spring boot多模塊項(xiàng)目(附源碼)

    這篇文章主要介紹了詳解Maven 搭建spring boot多模塊項(xiàng)目(附源碼),具有一定的參考價(jià)值,有興趣的可以了解一下
    2017-09-09
  • Java中Double除保留后小數(shù)位的幾種方法(小結(jié))

    Java中Double除保留后小數(shù)位的幾種方法(小結(jié))

    這篇文章主要介紹了Java中Double保留后小數(shù)位的幾種方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-07-07
  • Java框架Quartz中的Trigger簡(jiǎn)析

    Java框架Quartz中的Trigger簡(jiǎn)析

    這篇文章主要介紹了Java框架Quartz中的Trigger簡(jiǎn)析,所有類型的trigger都有TriggerKey這個(gè)屬性,表示trigger的身份;除此之外,trigger還有很多其它的公共屬性,這些屬性,在構(gòu)建trigger的時(shí)候可以通過TriggerBuilder設(shè)置,需要的朋友可以參考下
    2023-11-11
  • JavaWeb項(xiàng)目中DLL文件動(dòng)態(tài)加載方法

    JavaWeb項(xiàng)目中DLL文件動(dòng)態(tài)加載方法

    在JavaWeb項(xiàng)目中,有時(shí)候我們需要在運(yùn)行時(shí)動(dòng)態(tài)加載DLL文件(在Windows中是DLL,在Linux中是SO文件),這通常用于實(shí)現(xiàn)一些特定的功能,比如調(diào)用本機(jī)代碼或者使用某些特定于操作系統(tǒng)的API,本文將介紹如何在JavaWeb項(xiàng)目中動(dòng)態(tài)加載DLL文件,需要的朋友可以參考下
    2024-12-12
  • Java Web實(shí)現(xiàn)文件下載和亂碼處理方法

    Java Web實(shí)現(xiàn)文件下載和亂碼處理方法

    文件上傳和下載是web開發(fā)中常遇到的問題。今天小編給大家分享下Java Web實(shí)現(xiàn)文件下載和亂碼處理方法的相關(guān)資料,需要的朋友可以參考下
    2016-10-10
  • SpringBoot使用TraceId進(jìn)行日志鏈路追蹤的實(shí)現(xiàn)步驟

    SpringBoot使用TraceId進(jìn)行日志鏈路追蹤的實(shí)現(xiàn)步驟

    有時(shí)候一個(gè)業(yè)務(wù)調(diào)用鏈場(chǎng)景,很長,調(diào)了各種各樣的方法,看日志的時(shí)候,各個(gè)接口的日志穿插,確實(shí)讓人頭大,所以為了解決這個(gè)問題,本文給大家介紹了SpringBoot使用TraceId進(jìn)行日志鏈路追蹤的實(shí)現(xiàn)步驟,需要的朋友可以參考下
    2024-11-11
  • Java 中函數(shù) Function 的使用和定義示例小結(jié)

    Java 中函數(shù) Function 的使用和定義示例小結(jié)

    這篇文章主要介紹了Java 中函數(shù) Function 的使用和定義小結(jié),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧
    2024-07-07
  • Java中的CyclicBarrier循環(huán)柵欄深入解析

    Java中的CyclicBarrier循環(huán)柵欄深入解析

    這篇文章主要介紹了Java中的CyclicBarrier循環(huán)柵欄深入解析,CycleBarrier 它就相當(dāng)于是一個(gè)柵欄,所有線程在到達(dá)柵欄后都需要等待其他線程,等所有線程都到達(dá)后,再一起通過,需要的朋友可以參考下
    2023-12-12
  • Spring Boot利用Java Mail實(shí)現(xiàn)郵件發(fā)送

    Spring Boot利用Java Mail實(shí)現(xiàn)郵件發(fā)送

    這篇文章主要為大家詳細(xì)介紹了Spring Boot利用Java Mail實(shí)現(xiàn)郵件發(fā)送,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-02-02
  • Java實(shí)現(xiàn)矩陣順時(shí)針旋轉(zhuǎn)90度的示例

    Java實(shí)現(xiàn)矩陣順時(shí)針旋轉(zhuǎn)90度的示例

    今天小編就為大家分享一篇Java實(shí)現(xiàn)矩陣順時(shí)針旋轉(zhuǎn)90度的示例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2019-01-01

最新評(píng)論

甘泉县| 双流县| 台江县| 广饶县| 大渡口区| 元朗区| 婺源县| 鄱阳县| 武山县| 东海县| 邹平县| 南丹县| 长岭县| 酉阳| 仙居县| 沁源县| 韩城市| 噶尔县| 徐闻县| 宜黄县| 固安县| 高尔夫| 革吉县| 旌德县| 深水埗区| 崇阳县| 土默特右旗| 壶关县| 临沭县| 巩义市| 汉源县| 中阳县| 长武县| 齐齐哈尔市| 伊宁县| 信阳市| 揭东县| 府谷县| 大同县| 盐城市| 缙云县|