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

spring中@Transactional?注解失效的原因及解決辦法

 更新時(shí)間:2024年06月05日 09:19:02   作者:睡個(gè)好覺  
面試中經(jīng)常會(huì)被問到事務(wù)失效的場(chǎng)景有哪些,本文主要介紹了spring中@Transactional?注解失效的原因及解決辦法,具有一定的參考價(jià)值,感興趣的可以了解一下

前言

面試中經(jīng)常會(huì)被問到事務(wù)失效的場(chǎng)景有哪些,其實(shí)在開發(fā)中,若是不了解事務(wù)失效的場(chǎng)景,當(dāng)你覺得加了事務(wù),就會(huì)回滾,就大錯(cuò)特錯(cuò)了,今天就來了解一下吧。

一、@Transactional 屬性介紹

1.事務(wù)的傳播行為:propagation

這就是我們常說的事務(wù)的七種傳播行為,默認(rèn)值:Propagation.REQUIRED

屬性解釋
Propagation.REQUIRED如果當(dāng)前存在事務(wù),則加入該事務(wù),如果當(dāng)前不存在事務(wù),則創(chuàng)建一個(gè)新的事務(wù)。
Propagation.SUPPORTS如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前不存在事務(wù),則以非事務(wù)的方式繼續(xù)運(yùn)行。
Propagation.MANDATORY如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前不存在事務(wù),則拋出異常。
Propagation.REQUIRES_NEW重新創(chuàng)建一個(gè)新的事務(wù),如果當(dāng)前存在事務(wù),暫停當(dāng)前的事務(wù)。
Propagation.NOT_SUPPORTED以非事務(wù)的方式運(yùn)行,如果當(dāng)前存在事務(wù),暫停當(dāng)前的事務(wù)。
Propagation.NEVER以非事務(wù)的方式運(yùn)行,如果當(dāng)前存在事務(wù),則拋出異常。
Propagation.NESTED嵌套事務(wù)。

2.事務(wù)的隔離級(jí)別:isolation

這就是我們常說的事務(wù)的隔離級(jí)別,默認(rèn)值:Isolation.DEFAULT

屬性解釋
Isolation.DEFAULT使用底層數(shù)據(jù)庫默認(rèn)的隔離級(jí)別
Isolation.READ_UNCOMMITTED讀未提交
Isolation.READ_COMMITTED讀已提交
Isolation.REPEATABLE_READ可重復(fù)讀
Isolation.SERIALIZABLE串行化

3.事務(wù)的超時(shí)時(shí)間:timeout

  • timeout :事務(wù)的超時(shí)時(shí)間,默認(rèn)值為 -1。如果超過該時(shí)間限制但事務(wù)還沒有完成,則自動(dòng)回滾事務(wù)。

4.事務(wù)的回滾類型:rollbackFor

  • rollbackFor :用于指定能夠觸發(fā)事務(wù)回滾的異常類型,可以指定多個(gè)異常類型。

二、@Transactional 失效場(chǎng)景

1.同一個(gè)類中方法調(diào)用,注解失效

場(chǎng)景重現(xiàn):當(dāng)調(diào)用 saveCabinet 方法時(shí),save 方法中出異常不會(huì)回滾,如下代碼

@Service
public class CabinetServiceImpl implements CabinetService {
    @Autowired
    private CabinetMapper cabinetMapper;
    @Override
    public void saveCabinet(Cabinet cabinet) {
        save(cabinet);
    }
    @Transactional(rollbackFor = Exception.class)
    public void save(Cabinet cabinet) {
        cabinetMapper.insert(cabinet);
        int i = 1/0;	// 模擬出錯(cuò)
    }
}

原因分析:spring 中采用動(dòng)態(tài)代理來實(shí)現(xiàn)事務(wù),當(dāng)同一個(gè)類調(diào)用 save 時(shí),不是代理類在調(diào)用,所以掃描不到事務(wù)注解

解決方案1:將 save 方法提到另一個(gè)類中,saveCabinet 調(diào)用另一個(gè)類的 save 方法(推薦使用)

// 當(dāng)前類
@Service
public class CabinetServiceImpl implements CabinetService {
    @Autowired
    private MethodTest methodTest;
    @Override
    public void saveCabinet(Cabinet cabinet) {
        methodTest.save(cabinet);
    }
}
// 另一個(gè)類
@Service
public class MethodTest {
    @Autowired
    private CabinetMapper cabinetMapper;
    
    @Transactional(rollbackFor = Exception.class)
    public void save(Cabinet cabinet) {
        cabinetMapper.insert(cabinet);
        int i = 1/0; 	// 模擬出錯(cuò)
    }
}

解決方案2:在 CabinetServiceImpl 中自己注入自己,用自己的代理類調(diào)用 save 方法,即 cabinetServiceImpl.save()

@Service
public class CabinetServiceImpl implements CabinetService {
    @Autowired
    private CabinetMapper cabinetMapper;
    
    @Autowired
    private CabinetServiceImpl cabinetServiceImpl;
    
    @Override
    public void saveCabinet(Cabinet cabinet) {
        cabinetServiceImpl.save(cabinet);
    }
    
    @Transactional(rollbackFor = Exception.class)
    public void save(Cabinet cabinet) {
        cabinetMapper.insert(cabinet);
        int i = 1/0;	// 模擬出錯(cuò)
    }
}

2.異常被 catch “吃了”,注解失效

場(chǎng)景重現(xiàn):當(dāng)調(diào)用 saveCabinet 方法時(shí),方法體被 try-catch 了,不會(huì)回滾,如下代碼

@Service
public class CabinetServiceImpl implements CabinetService {
    @Autowired
    private CabinetMapper cabinetMapper;
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveCabinet(Cabinet cabinet) {
        try {
            cabinetMapper.insert(cabinet);
            int i = 1/0;	// 模擬出錯(cuò)
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

原因分析:異常直接捕獲沒有向上拋出,而是自己處理了,注解捕獲不到異常,所以失效

解決方案:將 catch 到的異常向上拋出 throw new Exception(e);,異常交給注解處理

@Service
public class CabinetServiceImpl implements CabinetService {
    @Autowired
    private CabinetMapper cabinetMapper;
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveCabinet(Cabinet cabinet) throws Exception {
        try {
            cabinetMapper.insert(cabinet);
            int i = 1/0;	// 模擬出錯(cuò)
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception(e);
        }
    }
}

3.@Transactional 應(yīng)用在非 public 修飾的方法上

  • 場(chǎng)景重現(xiàn):當(dāng)調(diào)用的方法不是 public 修飾時(shí),不會(huì)回滾,事務(wù)失效
  • 原因分析:在 spring aop 代理時(shí),事務(wù)攔截器會(huì)在目標(biāo)方法的執(zhí)行前后進(jìn)行攔截,其中的方法會(huì)去獲取 Transactional 注解的一些信息,而其中的方法會(huì)去檢查目標(biāo)方法是否被 public 修飾,不是的話獲取不到注解信息
  • 解決方案:將調(diào)用的方法訪問修飾符改為 public

4.@Transactional 注解屬性 rollbackFor 設(shè)置錯(cuò)誤

場(chǎng)景重現(xiàn):當(dāng)注解沒有指定 rollbackFor 屬性時(shí),如下若拋出 FileNotFoundException 異常則不會(huì)回滾

@Service
public class CabinetServiceImpl implements CabinetService {
    @Autowired
    private CabinetMapper cabinetMapper;
    
    @Override
    @Transactional
    public void saveCabinet(Cabinet cabinet) throws IOException {
        cabinetMapper.insert(cabinet);
        // 模擬出錯(cuò)
        throw new FileNotFoundException();
    }
}

原因分析:spring 默認(rèn)拋出未檢查異常,繼承 RuntimeException 或者 Error 才會(huì)回滾,其他異常如 FileNotFoundException 則不會(huì)回滾

解決方案:指定 rollbackFor 屬性,一般指定 @Transactional(rollbackFor = Exception.class) 即可,也可以指定自定義異常

@Service
public class CabinetServiceImpl implements CabinetService {
    @Autowired
    private CabinetMapper cabinetMapper;
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveCabinet(Cabinet cabinet) throws IOException {
        cabinetMapper.insert(cabinet);
        // 模擬出錯(cuò)
        throw new FileNotFoundException();
    }
}

5.@Transactional 注解屬性 propagation 設(shè)置錯(cuò)誤

  • 使用了不支持事務(wù)的傳播屬性

6.數(shù)據(jù)庫引擎不支持事務(wù)

  • 數(shù)據(jù)庫不支持事務(wù)

總結(jié)

到此這篇關(guān)于spring中@Transactional 注解失效的原因及解決辦法的文章就介紹到這了,更多相關(guān)spring @Transactional 失效內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot自動(dòng)配置類加載順序與優(yōu)先級(jí)

    SpringBoot自動(dòng)配置類加載順序與優(yōu)先級(jí)

    本文詳細(xì)介紹了Spring?Boot自動(dòng)配置類的加載順序與優(yōu)先級(jí),首先說明了加載順序的重要性及典型問題,然后拆解了Spring?Boot的默認(rèn)優(yōu)先級(jí)體系,需要的朋友可以參考下
    2026-04-04
  • Java語言實(shí)現(xiàn)非遞歸實(shí)現(xiàn)樹的前中后序遍歷總結(jié)

    Java語言實(shí)現(xiàn)非遞歸實(shí)現(xiàn)樹的前中后序遍歷總結(jié)

    今天小編就為大家分享一篇關(guān)于Java語言實(shí)現(xiàn)非遞歸實(shí)現(xiàn)樹的前中后序遍歷總結(jié),小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • Spring深入分析容器接口作用

    Spring深入分析容器接口作用

    Spring內(nèi)部提供了很多表示Spring容器的接口和對(duì)象,我們今天來看看幾個(gè)比較常見的容器接口和具體的實(shí)現(xiàn)類,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • 數(shù)組在java中的擴(kuò)容的實(shí)例方法

    數(shù)組在java中的擴(kuò)容的實(shí)例方法

    在本篇文章里小編給大家分享的是一篇關(guān)于數(shù)組在java中的擴(kuò)容的實(shí)例方法內(nèi)容,有興趣的朋友們可以學(xué)習(xí)下。
    2021-01-01
  • Java異常堆棧打印次數(shù)限制機(jī)制用法詳解

    Java異常堆棧打印次數(shù)限制機(jī)制用法詳解

    在Java開發(fā)中,異常處理是保證程序健壯性的重要手段,但當(dāng)同一個(gè)異常被頻繁拋出時(shí),日志可能會(huì)被大量重復(fù)的堆棧信息淹沒,影響問題排查效率,所以本文給大家介紹了Java異常堆棧打印次數(shù)限制機(jī)制的用法,需要的朋友可以參考下
    2025-04-04
  • SpringBoot事件監(jiān)聽器@EventListener的實(shí)現(xiàn)

    SpringBoot事件監(jiān)聽器@EventListener的實(shí)現(xiàn)

    @EventListener注解用于處理應(yīng)用程序事件,提供了一種方便的方式來監(jiān)聽和響應(yīng)各種事件,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-11-11
  • 最新評(píng)論

    嘉定区| 卢龙县| 天气| 定远县| 临澧县| 垫江县| 巩留县| 呈贡县| 铅山县| 浑源县| 中卫市| 行唐县| 高碑店市| 衡阳市| 西青区| 综艺| 外汇| 蓝田县| 泌阳县| 武胜县| 远安县| 高雄县| 墨脱县| 嘉荫县| 马鞍山市| 棋牌| 金门县| 达拉特旗| 北辰区| 长乐市| 鄂州市| 女性| 淮阳县| 南皮县| 都匀市| 陈巴尔虎旗| 英吉沙县| 清新县| 松潘县| 蒲城县| 会昌县|