@Transactional失效的場景

  1. 直接在同一個類內(nèi)部調(diào)用 @Transactional 方法
    失效示例
@Service
public class SomeService {

    @Transactional
    public void doSomethingTransactional() {
        // 進行一些數(shù)據(jù)庫操作
        System.out.println("Doing transactional work...");
    }

    public void callNonTransactional() {
        doSomethingTransactional();  // 事務(wù)失效,因為是內(nèi)部方法調(diào)用
    }
}

問題:callNonTransactional() 方法直接調(diào)用了 doSomethingTransactional(),而沒有通過 Spring 容器管理的代理調(diào)用,因此事務(wù)不會生效。
成功示例

@Service
public class SomeService {

    @Autowired
    private SomeService someService; // 依賴注入

    @Transactional
    public void doSomethingTransactional() {
        // 進行一些數(shù)據(jù)庫操作
        System.out.println("Doing transactional work...");
    }

    public void callNonTransactional() {
        someService.doSomethingTransactional();  // 通過 Spring 管理的實例調(diào)用,事務(wù)生效
    }
}

解決方法:

將 SomeService 注入到自己類中,并通過依賴注入調(diào)用 doSomethingTransactional() 方法,這樣 Spring 會通過代理進行方法調(diào)用,事務(wù)管理就能生效。


  1. 在非 Spring 管理的類中使用 @Transactional
    失效示例:
public class NonSpringManagedClass {

    @Transactional
    public void doSomething() {
        // 進行一些數(shù)據(jù)庫操作
        System.out.println("Transactional work in non-Spring managed class...");
    }
}

問題:NonSpringManagedClass 不是一個 Spring 管理的 Bean,因此事務(wù)注解不會生效。
成功示例

@Component  // 讓該類成為 Spring 管理的 Bean
public class NonSpringManagedClass {

    @Transactional
    public void doSomething() {
        // 進行一些數(shù)據(jù)庫操作
        System.out.println("Transactional work in Spring managed class...");
    }
}

解決方法:使用 @Component、@Service 或 @Repository 等注解將類標(biāo)記為 Spring 管理的 Bean,這樣 Spring 會為它創(chuàng)建代理,事務(wù)注解才會生效。


  1. 構(gòu)造函數(shù)上使用 @Transactional
    失效示例:
@Service
public class SomeService {
    @Transactional
    public SomeService() {  // 事務(wù)失效:構(gòu)造函數(shù)不能使用 @Transactional
        System.out.println("Initializing with transactional work...");
    }
}

問題:構(gòu)造函數(shù)不能使用 @Transactional 注解,因為事務(wù)只能應(yīng)用于實例方法。
解決示例

@Service
public class SomeService {

    @Transactional
    public void doTransactionalWork() {
        System.out.println("Doing transactional work...");
    }
}

  1. 在事務(wù)方法內(nèi)部捕獲異常
    失效示例:
@Service
public class SomeService {

    @Transactional
    public void doSomething() {
        try {
            // 可能拋出 RuntimeException
            throw new RuntimeException("Something went wrong");
        } catch (RuntimeException e) {
            // 異常被捕獲,事務(wù)不會回滾
            System.out.println("Exception caught, transaction will not rollback.");
        }
    }
}

問題:捕獲并處理了 RuntimeException 異常,導(dǎo)致 Spring 無法觸發(fā)事務(wù)回滾。

@Service
public class SomeService {

    @Transactional
    public void doSomething() {
        // 不捕獲異常,直接拋出
        throw new RuntimeException("Something went wrong");
    }
}

解決方法:

讓異常 不被捕獲,或者明確讓 Spring 了解哪些異常需要回滾(通過 rollbackFor 屬性)。
例如,使用 @Transactional(rollbackFor = RuntimeException.class) 來指定哪些異常需要觸發(fā)事務(wù)回滾。


備注:

當(dāng)方法一parentMethod 調(diào)用方法二childMethod時不同情況說明:
eg: @Transactional(rollbackFor = {Exception.class}, timeout = 2, propagation = Propagation.REQUIRED),@Transactional 注解傳播行為 propagation 屬性默認(rèn)值是 Propagation.REQUIRED,即當(dāng)前存在就加入,當(dāng)前不存在則創(chuàng)建

情況 parentMethod 是否加 @Transactional childMethod 是否加 @Transactional 事務(wù)行為 異常處理
情況 1 兩個方法都不在事務(wù)管理范圍內(nèi),每個數(shù)據(jù)庫操作獨立執(zhí)行 出現(xiàn)異常時,已執(zhí)行的數(shù)據(jù)庫操作不會回滾
情況 2 parentMethod 處于事務(wù)管理范圍,childMethod 不在事務(wù)管理范圍,childMethod 操作不參與 parentMethod 的事務(wù) - childMethod 異常,parentMethod 事務(wù)不回滾
- parentMethod 異常,parentMethod 事務(wù)回滾,childMethod 已執(zhí)行操作不受影響
情況 3 parentMethod 不在事務(wù)管理范圍,childMethod 處于事務(wù)管理范圍,childMethod 創(chuàng)建新事務(wù) - childMethod 異常,其事務(wù)回滾
- parentMethod 操作不受影響,因本身不在事務(wù)中
情況 4 是(不指定傳播行為) 是(不指定傳播行為) parentMethod 開啟事務(wù),childMethod 加入 parentMethod 的事務(wù),二者共享事務(wù)上下文 任何一個方法異常,整個事務(wù)回滾
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容