Spring 聲明式事務的核心在於傳播行為,定義當事務方法被另一個事務方法呼叫時,事務如何邊界延伸或隔離。TransactionDefinition 介面定義了 7 種傳播屬性,本文逐一解析並結合實例說明行為差異。
| 常數 | 行為描述 | 典型用途 |
|---|---|---|
| PROPAGATION_REQUIRED | 支援目前事務;若無則新建。最常用。 | 一般業務方法 |
| PROPAGATION_SUPPORTS | 支援目前事務;若無則以非事務方式執行。 | 唯讀查詢、不需事務保護的操作 |
| PROPAGATION_MANDATORY | 必須在現有事務中執行;若無則拋出異常。 | 強制要求事務上下文的核心邏輯 |
| PROPAGATION_REQUIRES_NEW | **新建事務**;若有現有事務則掛起。 | 獨立提交/回滾的操作(如日誌記錄、審計) |
| PROPAGATION_NOT_SUPPORTED | 以非事務方式執行;若有現有事務則掛起。 | 不需事務、效能優先的操作 |
| PROPAGATION_NEVER | 以非事務方式執行;若有現有事務則拋出異常。 | 嚴禁事務環境的特殊邏輯 |
| PROPAGATION_NESTED | 支援目前事務,設定儲存點;與外層事務同步提交/回滾。 | 部分回滾、多階段提交的複雜業務 |
ServiceA {
void methodA() {
ServiceB.methodB();
}
}
ServiceB {
void methodB() { /* ... */ }
}
假設 methodA 與 methodB 分別配置不同傳播屬性,分析互動行為。
methodA 有事務 → methodB 加入同一事務。methodA 無事務 → methodB 新建事務。methodB 已做的操作)。IllegalTransactionStateException。methodB **永遠在獨立新事務**執行,methodA 事務掛起。methodB 提交後,methodA 回滾**不影響** methodB。methodB 回滾若被 methodA 捕獲異常,methodA 仍可選擇提交。methodB 以非事務方式執行,methodA 事務掛起等待。void methodA() {
try {
ServiceB.methodB(); // NESTED
} catch (Exception e) {
// 回滾到 Savepoint,嘗試替代方案
ServiceC.methodC();
}
}
與 REQUIRES_NEW 差異:NESTED 依賴外層事務,**無獨立提交**,提交/回滾與外層同步;REQUIRES_NEW 完全獨立。
精通事務傳播屬性,能精準控制事務邊界,避免資料不一致或效能浪費。實務上以 REQUIRED 為主,輔以 REQUIRES_NEW 處理獨立副作用,NESTED 處理複雜回滾邏輯,構建健壯的事務架構。