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

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

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

前言

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

一、@Transactional 屬性介紹

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

這就是我們常說(shuō)的事務(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

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

屬性解釋
Isolation.DEFAULT使用底層數(shù)據(jù)庫(kù)默認(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。如果超過(guò)該時(shí)間限制但事務(wù)還沒(méi)有完成,則自動(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)代理來(lá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();
        }
    }
}

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

解決方案:將 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)用的方法訪問(wèn)修飾符改為 public

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

場(chǎng)景重現(xiàn):當(dāng)注解沒(méi)有指定 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ù)庫(kù)引擎不支持事務(wù)

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

總結(jié)

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

相關(guān)文章

最新評(píng)論