Spring事务中A方法调用B方法,B方法无事务注解,事务如何传播?

Spring事务中A方法调用B方法,B方法无事务注解,事务如何传播?
最新回答
夏迟归

2022-03-21 07:52:24

在Spring事务中,当A方法带有@Transactional注解并调用B方法(无事务注解)时,事务的传播行为遵循Spring的默认规则,具体如下:

核心结论
  • B方法的操作会参与A方法的事务,与A方法的数据库操作一起提交或回滚。
  • 事务传播行为由Spring的默认策略PROPAGATION_REQUIRED决定。
详细分析
  1. 事务传播机制Spring默认的事务传播行为是PROPAGATION_REQUIRED,其含义为:

    若当前存在事务(如A方法已开启事务),则B方法会加入该事务,成为同一事务的一部分。

    若当前不存在事务,则B方法会新建一个独立事务。在本场景中,A方法已开启事务,因此B方法会直接加入A的事务,无需新建事务。

  2. 事务一致性

    提交逻辑:若B方法执行成功,且A方法未发生异常,则A和B的所有数据库操作将一并提交

    回滚逻辑:若B方法抛出运行时异常(RuntimeException或其子类),Spring会标记当前事务为回滚状态,导致A和B的所有操作全部回滚

    检查型异常(Checked Exception):默认情况下,检查型异常不会触发回滚,除非通过@Transactional(rollbackFor=Exception.class)显式配置。

  3. 关键注意事项

    异常类型的影响:仅运行时异常会默认触发回滚,检查型异常需额外配置。

    方法调用方式:若A和B方法在同一个类中,且A通过this.B()调用B,事务可能失效(因Spring的事务基于代理机制,同类内部调用会绕过代理)。此时需通过依赖注入或AOP代理调用B方法。

    事务隔离级别:B方法继承A方法的事务隔离级别,无需单独配置。

示例场景@Servicepublic class MyService { @Transactional public void methodA() { // 数据库操作1(A的事务范围) methodB(); // 调用无事务注解的B方法 // 数据库操作2(A的事务范围) } public void methodB() { // 数据库操作3(加入A的事务) // 若此处抛出RuntimeException,A和B的所有操作将回滚 }}
  • 成功路径:methodA和methodB的所有操作均提交。
  • 失败路径:methodB抛出RuntimeException,导致methodA和methodB的操作全部回滚。
总结
  • B方法无事务注解时,默认加入A方法的事务(PROPAGATION_REQUIRED)。
  • 事务一致性:A和B的操作同生共死,由运行时异常触发整体回滚。
  • 配置建议:若需检查型异常触发回滚,需在@Transactional中指定rollbackFor。
  • 调用方式:确保跨方法调用通过代理实现,避免同类内部调用导致事务失效。