偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

必看!導(dǎo)致事務(wù)失效的七大典型場景!

開發(fā) 前端
@Transactional 聲明式事務(wù)失效的場景是 Java 面試中經(jīng)常被問到的問題,所以今天咱們就來系統(tǒng)的盤點(diǎn)一下導(dǎo)致 @Transactional 失效的場景有哪些?以及導(dǎo)致的原因和解決方案詳解。

@Transactional 聲明式事務(wù)失效的場景是 Java 面試中經(jīng)常被問到的問題,所以今天咱們就來系統(tǒng)的盤點(diǎn)一下導(dǎo)致 @Transactional 失效的場景有哪些?以及導(dǎo)致的原因和解決方案詳解。

1.方法訪問修飾符不是public

以下代碼會導(dǎo)致 @Transactional 失效:

@Service
public class OrderService {
    @Transactional
    private void createOrder() { // private方法,事務(wù)不生效
        // ...
    }
}

原因分析

Spring AOP 代理在生成代理類時,只對 public 方法生成事務(wù)代理,這是 Java 源碼層面設(shè)計(jì)原因,設(shè)計(jì)源碼如下:

protected TransactionAttribute computeTransactionAttribute(Method method, Class<?> targetClass) {
   // Don't allow no-public methods as required.
   // 非 public 方法,設(shè)置為 null
   if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
      return null;
   }
   // 后面代碼省略....
 }

解決方案

將方法改為 public。

2.自調(diào)用問題

以下代碼會導(dǎo)致 @Transactional 失效:

@Service
public class OrderService {
    public void placeOrder() {
        createOrder(); // 直接調(diào)用,繞過代理
    }

    @Transactional
    public void createOrder() {
        // 事務(wù)操作
    }
}

原因分析

當(dāng)一個類中的非事務(wù)方法調(diào)用本類的事務(wù)方法時,調(diào)用是通過 this 直接調(diào)用,而不是通過 Spring 代理對象調(diào)用,因此事務(wù)不能生效。

解決方案

  • 將事務(wù)方法移到另一個 Service 類中
  • 使用 ApplicationContext 獲取當(dāng)前 Bean 的代理對象,如下代碼所示:
@Autowired
private ApplicationContext context;

public void placeOrder() {
    OrderService proxy = context.getBean(OrderService.class);
    proxy.createOrder(); // 通過代理調(diào)用
}

3.異常被捕獲且未重新拋出

以下代碼會導(dǎo)致 @Transactional 失效:

@Transactional
public void transferMoney() {
    deductMoney();
    try {
        addMoney();
    } catch (Exception e) {
        log.error("異常", e);
        // 捕獲但未拋出,事務(wù)不會回滾
    }
}

原因分析

Spring 事務(wù)默認(rèn)只在拋出未被捕獲的 RuntimeException 或 Error 時回滾。如果異常被捕獲且未拋出,代理認(rèn)為方法執(zhí)行成功,會提交事務(wù)。

解決方案

  • 手動設(shè)置回滾:TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
  • 或重新拋出異常
@Transactional
public void transferMoney() {
    deductMoney();
    try {
        addMoney();
    } catch (Exception e) {
        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        throw e; // 或不拋出,僅setRollbackOnly
    }
}

4.事務(wù)傳播機(jī)制配置錯誤

例如:使用了 Propagation.NOT_SUPPORTED 或 Propagation.NEVER,會導(dǎo)致事務(wù)被掛起或拒絕。

特別注意 Propagation.REQUIRES_NEW:會掛起當(dāng)前事務(wù),開啟新事務(wù),需謹(jǐn)慎使用,避免嵌套事務(wù)導(dǎo)致性能問題或死鎖。

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

例如:MySQL 的 MyISAM 引擎不支持事務(wù),必須使用 InnoDB。

即使代碼配置了@Transactional,底層數(shù)據(jù)庫不支持也無法實(shí)現(xiàn)事務(wù)。

6.方法被final或static修飾

CGLIB 無法代理 final 方法(不能被重寫),JDK 代理也無法處理 static 方法,都會導(dǎo)致事務(wù)無法生效。因?yàn)?Spring/Spring Boot 是使用 CGLIB 或 JDK 代理實(shí)現(xiàn)的。

7.多線程中調(diào)用事務(wù)方法

以下代碼會導(dǎo)致 @Transactional 失效:

@Transactional
public void process() {
    new Thread(() -> {
        dao.update(); // 在子線程中,無事務(wù)
    }).start();
}

原因分析

事務(wù)是基于線程綁定的(通過 ThreadLocal 存儲事務(wù)上下文),子線程中調(diào)用事務(wù)方法時,無法繼承父線程的事務(wù)上下文。

解決方案

使用事務(wù)同步或手動管理事務(wù)。

小結(jié)

@Transactional 聲明式事務(wù)底層是通過 CGLIB 或 JDK 代理實(shí)現(xiàn)的,所以事務(wù)失效的場景多半與二者相關(guān),本文總共介紹了 7 種導(dǎo)致事務(wù)失效的場景,您至少要記住其中 4 種以上事務(wù)失效場景,這樣才能在面試中嶄露頭角。


責(zé)任編輯:武曉燕 來源: 磊哥和Java
相關(guān)推薦

2015-03-25 09:19:17

云計(jì)算云部署項(xiàng)目部署失敗原因

2021-09-26 05:38:16

云計(jì)算云計(jì)算環(huán)境云應(yīng)用

2013-01-06 09:59:08

2024-07-31 16:04:14

2018-05-06 22:53:36

物聯(lián)網(wǎng)NB-IOT窄帶物聯(lián)網(wǎng)

2018-02-24 05:40:02

2018-01-22 08:18:47

混合云云應(yīng)用多云

2023-02-21 09:16:00

CPU散熱器超頻

2017-04-22 11:26:01

2013-08-27 17:55:23

2022-02-14 16:53:57

Spring項(xiàng)目數(shù)據(jù)庫

2015-01-04 09:17:18

2018-04-11 14:13:29

物聯(lián)網(wǎng)信息技術(shù)互聯(lián)網(wǎng)

2009-12-01 14:35:06

Linux忠告

2020-12-22 09:55:55

IT首席信息官CIO

2015-07-08 08:51:11

SDN

2020-12-18 10:35:27

IT技術(shù)領(lǐng)導(dǎo)者

2022-05-23 08:09:42

物聯(lián)網(wǎng)IOT

2025-02-10 00:27:54

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號