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

spring 中事務(wù)注解@Transactional與trycatch的使用

 更新時(shí)間:2021年06月21日 15:32:46   作者:浪老貓  
這篇文章主要介紹了spring 中事務(wù)注解@Transactional與trycatch的使用,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

spring事務(wù)注解@Transactional與trycatch

在項(xiàng)目中 @service層中 我們會經(jīng)常在做一些增刪改操作的方法上看到 spring 的事務(wù)注解 @transaction 已知@transaction 是讓spring 幫我們實(shí)現(xiàn)事務(wù)的控制。

但是在項(xiàng)目中會經(jīng)??吹?有的方法中 會存在trycatch塊包括的方法上注解著@transaction

eg:

 @Override
    @Transactional
    public Json addOrder(TOrderAddReq tOrderAddReq) {
  try{
    //增刪改方法
        } catch (Exception e) {
            .....
            e.printStackTrace();}
//        }
        return json;
    }

上述的方法執(zhí)行后可以看到事務(wù)并沒有執(zhí)行,接下來再看一個(gè)例子eg:

 @Override
    @Transactional
    public Json addOrder(TOrderAddReq tOrderAddReq) {
  try{
    //增刪改方法
        } catch (Exception e) {
         // 手動(dòng)硬編碼開啟spring事務(wù)管理
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            e.printStackTrace();}
//        }
        return json;
    }

上述方法執(zhí)行后我們可以看到事務(wù)最后執(zhí)行了,但實(shí)際上 事務(wù) 執(zhí)行只是因?yàn)槭謩?dòng)硬編碼開啟spring事務(wù)管理起了作用 而方法上的注解并沒有起作用

接下來再看一個(gè)例子eg

 @Override
    @Transactional
    public Json addOrder(TOrderAddReq tOrderAddReq) {
  try{
    //增刪改方法
        } catch (Exception e) {
         
            throw new RuntimeException();
            }
//        }
        return json;
    }

上述方法執(zhí)行后我們可以看到事務(wù)是執(zhí)行了的,但這里有個(gè)小細(xì)節(jié):@Transactional不做任何配置 默認(rèn)是對拋出的unchecked異常回滾,checked異常不會回滾,為了讓所有異常都會讓事務(wù)啟動(dòng)可以將 @Transactional配置為 @Transactional(rollbackFor = Exception.class)

解釋:

spring的事務(wù)邊界是在調(diào)用業(yè)務(wù)方法之前開始的,業(yè)務(wù)方法執(zhí)行完畢之后來執(zhí)行commit or rollback(spring默認(rèn)取決于是否拋出runtime異常).

如果拋出runtime exception 并在你的業(yè)務(wù)方法中沒有catch到的話,事務(wù)會回滾。

一般不需要在業(yè)務(wù)方法中catch異常,如果非要catch,在做完你想做的工作后(比如關(guān)閉文件等)一定要拋出runtime exception,否則spring會將你的操作commit,這樣就會產(chǎn)生臟數(shù)據(jù).所以你的catch代碼是畫蛇添足。

@Transactional回滾問題(try catch、嵌套)

Spring 事務(wù)注解 @Transactional 本來可以保證原子性,如果事務(wù)內(nèi)有報(bào)錯(cuò)的話,整個(gè)事務(wù)可以保證回滾,但是加上try catch或者事務(wù)嵌套,可能會導(dǎo)致事務(wù)回滾失敗。測試一波。

準(zhǔn)備

建兩張表,模擬兩個(gè)數(shù)據(jù)操作

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) DEFAULT NULL,
  `age` smallint(3) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
CREATE TABLE `role` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `role_name` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

測試

根據(jù)排列組合原理,我們進(jìn)行四種測試:1、無try catch、無嵌套;2、有try catch、無嵌套;3、無try catch、有嵌套;4、都有。

最簡單測試

如果我們單純@Transactional,事務(wù)可以正?;貪L嗎?

    @GetMapping("/saveNormal0")
    @Transactional
    public void saveNormal0() throws Exception {
        int age = random.nextInt(100);
        User user = new User().setAge(age).setName("name:"+age);
        userService.save(user);
        throw new RuntimeException();
    }

如果事務(wù)內(nèi)報(bào)了RuntimeException錯(cuò)誤,事務(wù)可以回滾。

    @GetMapping("/saveNormal0")
    @Transactional
    public void saveNormal0() throws Exception {
        int age = random.nextInt(100);
        User user = new User().setAge(age).setName("name:"+age);
        userService.save(user);
        throw new Exception();
    }

如果事務(wù)內(nèi)報(bào)了Exception錯(cuò)誤(非RuntimeException錯(cuò)誤),事務(wù)不可以回滾。

    @GetMapping("/saveNormal0")
    @Transactional( rollbackFor = Exception.class)
    public void saveNormal0() throws Exception {
        int age = random.nextInt(100);
        User user = new User().setAge(age).setName("name:"+age);
        userService.save(user);
        throw new Exception();
    }

如果是Exception錯(cuò)誤(非RuntimeException),加上 rollbackFor = Exception.class 參數(shù)也可以實(shí)現(xiàn)回滾。

結(jié)論一:對于@Transactional可以保證RuntimeException錯(cuò)誤的回滾,如果想保證非RuntimeException錯(cuò)誤的回滾,需要加上rollbackFor = Exception.class 參數(shù)。

try catch 影響

經(jīng)過博主多種情況測試,發(fā)現(xiàn)try catch對回滾這個(gè)事本身沒有什么影響,結(jié)論一照樣成立。try catch只是對異常是否可以被@Transactional 感知 到有影響。如果錯(cuò)誤拋到切面可以感知到的地步,那就可以起作用。

    @GetMapping("/saveTryCatch")
    @Transactional( rollbackFor = Exception.class)
    public void saveTryCatch() throws Exception{
        try{
            int age = random.nextInt(100);
            User user = new User().setAge(age).setName("name:"+age);
            userService.save(user);
            throw new Exception();
        }catch (Exception e){
            throw e;
        }
    }

比如上面一段代碼就回滾了。

    @GetMapping("/saveTryCatch")
    @Transactional( rollbackFor = Exception.class)
    public void saveTryCatch() throws Exception{
        try{
            int age = random.nextInt(100);
            User user = new User().setAge(age).setName("name:"+age);
            userService.save(user);
            throw new Exception();
        }catch (Exception e){
        }
    }

然而,將catch中的錯(cuò)誤不繼續(xù)網(wǎng)上拋,切面無法感知到錯(cuò)誤,無法進(jìn)行處理,那么事務(wù)就無法回滾了。

結(jié)論二:try catch只是對異常是否可以被@Transactional 感知 到有影響。如果錯(cuò)誤拋到切面可以感知到的地步,那就可以起作用。

事務(wù)嵌套 影響

首先經(jīng)過實(shí)驗(yàn),結(jié)論一仍然成立,即,當(dāng)不加上rollbackFor = Exception.class 的時(shí)候,無論內(nèi)外報(bào)RuntimeException,都會回滾;無論內(nèi)外報(bào) 非RuntimeException 錯(cuò)誤,都不會回滾。如果加上rollbackFor = Exception.class,無論內(nèi)外怎么報(bào)錯(cuò),都會回滾。這些代碼就不給出了。接下來,試下下面兩種情況:

    @GetMapping("/out")
    @Transactional( rollbackFor = Exception.class)
    public void out() throws Exception{
        innerService.inner();
        int age = random.nextInt(100);
        User user = new User().setAge(age).setName("name:" + age);
        userService.save(user);
        throw new Exception();
    }
    @Transactional
    public void inner() throws Exception{
        Role role = new Role();
        role.setRoleName("roleName:"+new Random().nextInt(100));
        roleService.save(role);
//        throw new Exception();
    }

情況一,外面事務(wù)加上rollbackFor = Exception.class,里面事務(wù)不加,測試內(nèi)外分別報(bào)錯(cuò)的情況(為了簡化代碼量,只給出了外面報(bào)錯(cuò)的代碼),都可以回滾。因?yàn)?,無論如何,錯(cuò)誤都拋給了外面那個(gè)事務(wù)進(jìn)行處理,而外面那個(gè)加上了rollbackFor = Exception.class,具備處理非RuntimeException錯(cuò)誤的能力,所以都可以讓事務(wù)進(jìn)行正?;貪L。

下面看情況二,里面的事務(wù)加上rollbackFor = Exception.class,外面不加,外面報(bào)錯(cuò)。

    @GetMapping("/out")
    @Transactional
    public void out() throws Exception{
        innerService.inner();
        int age = random.nextInt(100);
        User user = new User().setAge(age).setName("name:" + age);
        userService.save(user);
        throw new Exception();
    }
    
    @Transactional( rollbackFor = Exception.class)
    public void inner() throws Exception{
        Role role = new Role();
        role.setRoleName("roleName:"+new Random().nextInt(100));
        roleService.save(role);
    }

事務(wù)都無法回滾,這是我們有個(gè)疑問,里面的事務(wù)明明有很強(qiáng)的處理能力啊,為什么和外面一起回滾失敗呢,別著急,等等聊這個(gè)。

然后試下里面報(bào)錯(cuò):

    @GetMapping("/out")
    @Transactional
    public void out() throws Exception{
        innerService.inner();
        int age = random.nextInt(100);
        User user = new User().setAge(age).setName("name:" + age);
        userService.save(user);
    }
     @Transactional( rollbackFor = Exception.class)
    public void inner() throws Exception{
        Role role = new Role();
        role.setRoleName("roleName:"+new Random().nextInt(100));
        roleService.save(role);
        throw new Exception();
    }

咦,這回都進(jìn)行了正常的回滾。我的天,這回外面沒有處理能力,為什么接受里面拋出來的錯(cuò)誤,也進(jìn)行了回滾?。?!看上去,就好像里外事務(wù)總是同生共死的對不對?原來,@Transactional還有個(gè)參數(shù),看下源碼,這個(gè)注解還有默認(rèn)值:

Propagation propagation() default Propagation.REQUIRED;

REQUIRED的意思是說,事務(wù)嵌套的時(shí)候,如果發(fā)現(xiàn)已經(jīng)有事務(wù)存在了,就加入這個(gè)事務(wù),而不是新建一個(gè)事務(wù),所以根本就不存在兩個(gè)事務(wù),一直只有一個(gè)!至于,此參數(shù)其他值,本文不進(jìn)行測試。回到上面的問題,當(dāng)外面報(bào)錯(cuò)的時(shí)候,此時(shí)查看事務(wù),沒有增加rollbackFor = Exception.class參數(shù),即沒有處理非RuntimeException能力,所以代碼走完,貌似“兩個(gè)事務(wù)”,都回滾失敗了。當(dāng)里面報(bào)錯(cuò)的時(shí)候,事務(wù)已經(jīng)添加上了處理非RuntimeException能力,所以,代碼走完就回滾成功了。

結(jié)論三:由于REQUIRED屬性,“兩個(gè)事務(wù)”其實(shí)是一個(gè)事務(wù),處理能力看報(bào)錯(cuò)時(shí)刻,是否添加了處理非RuntimeException的能力。

try catch和事務(wù)嵌套 共同影響

在結(jié)論一二三成立的條件下,探索共同影響的問題就簡單多了,由于情況太多,就不進(jìn)行過多的代碼展示了。

結(jié)論

結(jié)論一:

對于@Transactional可以保證RuntimeException錯(cuò)誤的回滾,如果想保證非RuntimeException錯(cuò)誤的回滾,需要加上rollbackFor = Exception.class 參數(shù)。

結(jié)論二:

try catch只是對異常是否可以被@Transactional 感知 到有影響。如果錯(cuò)誤拋到切面可以感知到的地步,那就可以起作用。

結(jié)論三:

由于REQUIRED屬性,“兩個(gè)事務(wù)”其實(shí)是一個(gè)事務(wù),處理能力看報(bào)錯(cuò)時(shí)刻,是否添加了處理非RuntimeException的能力。

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

相關(guān)文章

  • 論java如何通過反射獲得方法真實(shí)參數(shù)名及擴(kuò)展研究

    論java如何通過反射獲得方法真實(shí)參數(shù)名及擴(kuò)展研究

    這篇文章主要為大家介紹了java如何通過反射獲得方法的真實(shí)參數(shù)名以及擴(kuò)展研究,有需要的朋友可以借鑒參考下,希望能夠有所幫助祝大家多多進(jìn)步早日升職加薪
    2022-01-01
  • SpringBoot項(xiàng)目導(dǎo)入外部jar包的詳細(xì)指南

    SpringBoot項(xiàng)目導(dǎo)入外部jar包的詳細(xì)指南

    在開發(fā)SpringBoot項(xiàng)目時(shí),我們經(jīng)常需要引入一些外部的jar包來增強(qiáng)項(xiàng)目的功能,這些jar包可能不是Maven中央倉庫中的,或者我們想要使用特定版本的jar包,本文將詳細(xì)介紹如何在SpringBoot項(xiàng)目中導(dǎo)入外部jar包,需要的朋友可以參考下
    2024-10-10
  • 詳解Java中的鎖Lock和synchronized

    詳解Java中的鎖Lock和synchronized

    鎖是Java并發(fā)編程中最重要的同步機(jī)制,Java提供了種類豐富的鎖,每種鎖因其特性的不同,在適當(dāng)?shù)膱鼍跋履軌蛘宫F(xiàn)出非常高的效率。本文將詳細(xì)介紹Lock和synchronized
    2021-06-06
  • SpringBoot整合RabbitMQ實(shí)現(xiàn)消息確認(rèn)機(jī)制

    SpringBoot整合RabbitMQ實(shí)現(xiàn)消息確認(rèn)機(jī)制

    這篇文章主要介紹了SpringBoot整合RabbitMQ實(shí)現(xiàn)消息確認(rèn)機(jī)制,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-08-08
  • Java基礎(chǔ)學(xué)習(xí)之集合底層原理

    Java基礎(chǔ)學(xué)習(xí)之集合底層原理

    今天帶大家回顧Java基礎(chǔ)的相關(guān)知識,文中對集合底層原理作了非常詳細(xì)的圖文介紹,對Java初學(xué)者有非常好的幫助,需要的朋友可以參考下
    2021-05-05
  • spring boot 使用utf8mb4的操作

    spring boot 使用utf8mb4的操作

    這篇文章主要介紹了spring boot 使用utf8mb4的操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-02-02
  • springboot如何使用MybatisPlus

    springboot如何使用MybatisPlus

    MyBatisPlus是一個(gè)強(qiáng)大的數(shù)據(jù)庫操作框架,其代碼生成器可以快速生成實(shí)體類、映射文件等,本文介紹了如何導(dǎo)入MyBatisPlus相關(guān)依賴,創(chuàng)建代碼生成器,并配置數(shù)據(jù)庫信息以逆向生成代碼,感興趣的朋友跟隨小編一起看看吧
    2024-09-09
  • SpringBoot 跨域問題的解決方案

    SpringBoot 跨域問題的解決方案

    這篇文章主要介紹了SpringBoot 跨域問題的解決方案,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-06-06
  • Java JVM字節(jié)碼指令集總結(jié)整理與介紹

    Java JVM字節(jié)碼指令集總結(jié)整理與介紹

    本節(jié)將會著重介紹一下JVM中的指令集、Java是如何跨平臺的、JVM指令集參考手冊等內(nèi)容。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-09-09
  • java substring 截取字符串的方法

    java substring 截取字符串的方法

    這篇文章主要介紹了java substring 截取字符串的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05

最新評論

奉贤区| 原平市| 葵青区| 炎陵县| 安西县| 遂川县| 黄石市| 遂昌县| 商河县| 封丘县| 竹北市| 博白县| 盐城市| 石嘴山市| 德令哈市| 武平县| 荥经县| 香河县| 蚌埠市| 香河县| 石狮市| 达孜县| 苗栗县| 津南区| 集贤县| 苍南县| 鸡东县| 乾安县| 上林县| 罗江县| 惠来县| 五指山市| 江安县| 银川市| 广河县| 娄烦县| 武胜县| 沭阳县| 泾源县| 平阳县| 景德镇市|