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

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

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

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

一、 spring 事務原理

一、Spring事務原理

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

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

Spring本身并不提供事務,而是對JDBC事務通過AOP做了封裝,隱藏了2和4的操作,簡化了JDBC的應用。

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

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

問題一、@Transactional 應該加到什么地方,如果加到Controller會回滾嗎?

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

下載代碼并啟動難項目進行驗證:主要代碼如下:
Controller層代碼如下:

 @Autowired
    private TransactionalService transactionalService;

    @Autowired
    private UserDao userDao;

    @Autowired
    private JwtUserDao jwtUserDao;

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

 /**
     * 測試@Transactional 注解加到Controller層事務是否回滾
     * 這里在Controller層為了方便直接調用了dao層,在實際開發(fā)中dao層即可在Controller層調用也可以在service層調用,
     * 比如service層只是直接調用dao層一個方法,此外沒有任何操作,那么這時候完全不用寫service層的方法,直接在Controller調用dao層即可,
     * 當然如果公司有規(guī)范,必須嚴格按照mvc的模式進行開發(fā),則另說
     */
    @Transactional(rollbackFor = Exception.class)
    @RequestMapping("/ctx2")
    public void cTX2(){
        userDao.update();
         //手動拋出一個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();
         //手動拋出一個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,由于本次使用測試代碼進行統(tǒng)一的異常處理所以瀏覽器的返回數(shù)據(jù)如下:

在這里插入圖片描述

控制臺輸出如下:

在這里插入圖片描述

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

在這里插入圖片描述

在這里插入圖片描述

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

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

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

在這里插入圖片描述

紅框中的內容如下:

rolling back on RuntimeException and Error but not on checked exceptions

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

在這里插入圖片描述

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

在這里插入圖片描述

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

在這里插入圖片描述

在這里插入圖片描述

問題三:事務調用嵌套問題具體結果如下代碼:

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

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


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

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

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

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

總結:如果在a方法中調用b方法不管是不是a和b是不是在同一個類中,只要a方法中沒有事務,則發(fā)生異常的時候不會回滾,即:當a無事務時,則a和b均沒有事務,當a有事務時,b如果有事務,則b事務會加到a事務中,二者為同一事務!

四、總結

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

五、 參考鏈接

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

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

相關文章

  • 一文吃透消息隊列RocketMQ實現(xiàn)消費冪等原理

    一文吃透消息隊列RocketMQ實現(xiàn)消費冪等原理

    這篇文章主要介紹了消息隊列RocketMQ實現(xiàn)消費冪等的全面講解,幫助大家吃透RocketMQ消息隊列消費冪等,更好的的應用與工作實踐,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2024-01-01
  • SpringBoot+Ajax+redis實現(xiàn)隱藏重要接口地址的方法

    SpringBoot+Ajax+redis實現(xiàn)隱藏重要接口地址的方法

    這篇文章主要介紹了SpringBoot+Ajax+redis實現(xiàn)隱藏重要接口地址,本篇文章主要講訴使用SpringBoot項目配合Ajax和redis實現(xiàn)隱藏重要接口地址,這里我以隱藏秒殺地址為例,需要的朋友可以參考下
    2024-03-03
  • Java OOP三大特征之封裝繼承與多態(tài)詳解

    Java OOP三大特征之封裝繼承與多態(tài)詳解

    本文主要講述的是面向對象的三大特性:封裝,繼承,多態(tài),內容含括從封裝到繼承再到多態(tài)的所有重點內容以及使用細節(jié)和注意事項,內容有點長,請大家耐心看完
    2022-07-07
  • Java中線程組ThreadGroup與線程池的區(qū)別及示例

    Java中線程組ThreadGroup與線程池的區(qū)別及示例

    這篇文章主要介紹了Java中線程組與線程池的區(qū)別及示例,ThreadGroup是用來管理一組線程的,可以控制線程的執(zhí)行,查看線程的執(zhí)行狀態(tài)等操作,方便對于一組線程的統(tǒng)一管理,需要的朋友可以參考下
    2023-05-05
  • Java實現(xiàn)表達式二叉樹

    Java實現(xiàn)表達式二叉樹

    這篇文章主要為大家詳細介紹了如何利用Java實現(xiàn)表達式二叉樹,感興趣的小伙伴們可以參考一下
    2016-08-08
  • Maven多模塊之父子關系的創(chuàng)建

    Maven多模塊之父子關系的創(chuàng)建

    這篇文章主要介紹了Maven多模塊之父子關系的創(chuàng)建,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-03-03
  • MyBatis-Plus的物理刪除和邏輯刪除(使用場景)

    MyBatis-Plus的物理刪除和邏輯刪除(使用場景)

    數(shù)據(jù)庫中的數(shù)據(jù)刪除會分為兩種:物理刪除 和 邏輯刪除,接下來通過本文給大家介紹MyBatis-Plus的物理刪除和邏輯刪除使用場景分析,感興趣的朋友一起看看吧
    2021-09-09
  • Java中Map的遍歷方法及性能測試

    Java中Map的遍歷方法及性能測試

    這篇文章主要介紹了Java中Map的遍歷方法及性能測試,本文講解對HashMap、TreeMap進行對比測試,給出測試代碼、測試結果和測試結論,需要的朋友可以參考下
    2015-01-01
  • SpringBoot中使用攔截器的配置詳解

    SpringBoot中使用攔截器的配置詳解

    這篇文章主要介紹了SpringBoot中使用攔截器的配置詳解,攔截器是?AOP?的一種實現(xiàn),專門攔截對動態(tài)資源的后臺請求,即攔截對控制層的請?求,使用場景比較多的是判斷用戶是否有權限請求后臺,需要的朋友可以參考下
    2024-01-01
  • spring boot高并發(fā)下耗時操作的實現(xiàn)方法

    spring boot高并發(fā)下耗時操作的實現(xiàn)方法

    這篇文章主要給大家介紹了關于spring boot高并發(fā)下耗時操作的實現(xiàn)方法,文中通過示例代碼介紹的非常詳細,對大家學習或者使用spring boot具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-11-11

最新評論