You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让方法在@Transactional回滚后自动调用

解决方案

方案1:Spring AOP 切面实现

利用Spring的AOP切面捕获doSomeThing()方法抛出的运行时异常(事务回滚的触发条件),在异常抛出后自动调用logInfo()方法。

核心注意点:要确保日志操作不受主事务回滚影响,需给logInfo()配置REQUIRES_NEW的事务传播特性,强制开启独立新事务。

修改后的服务类代码

@Transactional
public class TransactionalService {

    @Transactional
    public void doSomeThing() {
        // 业务逻辑,抛出异常会触发事务回滚
        throw new RuntimeException("模拟业务异常");
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void logInfo() {
        // 日志记录逻辑,此方法在独立事务中执行,不会被主事务回滚影响
        System.out.println("记录事务回滚日志:业务方法执行异常触发回滚");
    }
}

编写AOP切面类

@Component
@Aspect
public class TransactionRollbackAspect {

    @Autowired
    private TransactionalService transactionalService;

    // 定义切点:匹配TransactionalService类中的doSomeThing方法
    @Pointcut("execution(* com.yourpackage.TransactionalService.doSomeThing(..))")
    public void doSomeThingPointcut() {}

    // 切点方法抛出异常后执行回调
    @AfterThrowing(pointcut = "doSomeThingPointcut()", throwing = "ex")
    public void afterDoSomeThingThrow(Exception ex) {
        transactionalService.logInfo();
    }
}

方案2:TransactionSynchronizationManager 同步回调

在doSomeThing()方法内部,通过TransactionSynchronizationManager注册事务同步回调,当事务完成且状态为回滚时自动触发日志记录。这种方式无需额外切面,适合在方法内部直接处理。

修改后的服务类代码

@Transactional
public class TransactionalService {

    @Transactional
    public void doSomeThing() {
        // 注册事务同步回调
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
            @Override
            public void afterCompletion(int status) {
                // 判断事务是否回滚
                if (status == TransactionSynchronization.STATUS_ROLLED_BACK) {
                    logInfo();
                }
            }
        });

        // 业务逻辑,抛出异常触发回滚
        throw new RuntimeException("模拟业务异常");
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void logInfo() {
        // 日志记录逻辑
        System.out.println("记录事务回滚日志:事务已回滚");
    }
}

关键注意事项

  • 若未给logInfo()配置REQUIRES_NEW传播特性,日志操作会和主事务绑定,主事务回滚时日志也会被回滚,无法完成有效记录。
  • Spring事务默认仅捕获运行时异常(RuntimeException)和Error触发回滚,若需捕获检查型异常,需在@Transactional注解中指定rollbackFor属性,例如@Transactional(rollbackFor = Exception.class)。

内容的提问来源于stack exchange,提问作者aqsakd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 11:15:44