鼠扑 发表于 2025-4-2 23:33:10

Spring Boot 七种事件传播活动只有 REQUIRES_NEW 和 NESTED 支持部门回滚的分析

Spring Boot 七种事件传播活动支持部门回滚的分析

支持部门回滚的传播活动



[*]REQUIRES_NEW:始终开启新事件,独立于外部事件,失败时仅自身回滚。
[*]NESTED:在当前事件中创建生存点(Savepoint),可局部回滚到生存点,不影响外部事件整体提交。
代码示例:利用 REQUIRES_NEW 实现部门回滚

1. 交易服务层(独立事件)

@Service
public class TransactionService {

    @Autowired
    private 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 {

    @Autowired
    private 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 {

    @Autowired
    private BatchProcessor batchProcessor;
    @Autowired
    private TradeRepository tradeRepository;

    @Test
    public 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 {

    @Autowired
    private 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 {

    @Autowired
    private 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)。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: Spring Boot 七种事件传播活动只有 REQUIRES_NEW 和 NESTED 支持部门回滚的分析