Spring Boot 七種事務傳播行為支持部分回滾的分析
支持部分回滾的傳播行為
REQUIRES_NEW
:始終開啟新事務,獨立于外部事務,失敗時僅自身回滾。NESTED
:在當前事務中創建保存點(Savepoint),可局部回滾到保存點,不影響外部事務整體提交。
代碼示例:使用 REQUIRES_NEW
實現部分回滾
1. 交易服務層(獨立事務)
@Service
public class TransactionService {@Autowiredprivate TradeRepository tradeRepository;// 使用 REQUIRES_NEW,每個交易獨立事務@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)public void processTrade(Trade trade) {try {// 模擬業務邏輯(如保存交易)tradeRepository.save(trade);if (trade.getId() == 3) { // 模擬交易3失敗throw new RuntimeException("Transaction 3 failed");}} catch (Exception e) {// 本地異常處理,但事務仍會回滾throw e;}}
}
2. 批量任務協調者
@Service
public class BatchProcessor {@Autowiredprivate TransactionService transactionService;// 批量任務不開啟事務(NOT_SUPPORTED)@Transactional(propagation = Propagation.NOT_SUPPORTED)public void executeBatch(List<Trade> trades) {for (Trade trade : trades) {try {transactionService.processTrade(trade);} catch (Exception e) {// 記錄錯誤但繼續處理其他交易System.out.println("Trade " + trade.getId() + " failed!");}}}
}
3. 測試用例
@SpringBootTest
public class BatchTest {@Autowiredprivate BatchProcessor batchProcessor;@Autowiredprivate TradeRepository tradeRepository;@Testpublic void testBatchProcessing() {List<Trade> trades = Arrays.asList(new Trade(1, "Success1"),new Trade(2, "Success2"),new Trade(3, "Failed") // 交易3會失敗);batchProcessor.executeBatch(trades);// 驗證:交易1和2已提交,交易3未提交assertEquals(2, tradeRepository.count());}
}
代碼示例:使用 NESTED
實現部分回滾
1. 交易服務層(嵌套事務)
@Service
public class TransactionService {@Autowiredprivate TradeRepository tradeRepository;// 使用 NESTED,在外部事務中創建保存點@Transactional(propagation = Propagation.NESTED, rollbackFor = Exception.class)public void processTradeWithNested(Trade trade) {try {tradeRepository.save(trade);if (trade.getId() == 3) {throw new RuntimeException("Transaction 3 failed");}} catch (Exception e) {throw e; // 回滾到保存點,但外部事務可繼續提交其他交易}}
}
2. 批量任務協調者(需開啟外部事務)
@Service
public class BatchProcessor {@Autowiredprivate TransactionService transactionService;// 開啟外部事務(REQUIRED)@Transactional(propagation = Propagation.REQUIRED)public void executeBatchWithNested(List<Trade> trades) {for (Trade trade : trades) {try {transactionService.processTradeWithNested(trade);} catch (Exception e) {System.out.println("Trade " + trade.getId() + " failed!");// 繼續處理其他交易}}// 手動提交外部事務(可選,但通常由Spring自動管理)}
}
傳播行為對比表格
傳播行為 | 是否支持部分回滾 | 適用場景 | 代碼示例方法 |
---|---|---|---|
REQUIRED | ? 不支持 | 繼承父事務,失敗時所有操作回滾 | - |
REQUIRES_NEW | ? 支持 | 獨立事務,失敗不影響其他交易 | processTrade() |
SUPPORTS | ? 不支持 | 無事務或依賴父事務 | - |
NOT_SUPPORTED | ? 不支持 | 掛起父事務,無事務執行 | - |
MANDATORY | ? 不支持 | 必須存在父事務 | - |
NEVER | ? 不支持 | 禁止存在父事務 | - |
NESTED | ? 支持 | 在父事務中創建保存點,局部回滾 | processTradeWithNested() |
關鍵說明
-
REQUIRES_NEW
- 每個交易獨立開啟事務,失敗時僅自身回滾,其他交易不受影響。
- 適用場景:完全獨立的交易,彼此無依賴。
-
NESTED
- 在父事務中創建保存點,失敗時回滾到保存點,但父事務仍可提交。
- 適用場景:交易間有弱關聯,需局部回滾但整體提交成功。
注意:使用 NESTED
需確保數據庫和驅動支持保存點(如MySQL/PostgreSQL)。