@Transactional事务回滚时如何保留catch块内私有方法的DB写入数据
问题根源
你当前实现的核心问题是@Transactional标注的公共方法默认开启一个统一的逻辑事务,方法内所有数据库操作都会加入该事务。你在catch块重抛异常后,整个事务会触发全量回滚,catch块内写入的错误追踪数据自然也会被回滚。
另外受Spring AOP的代理机制限制,私有方法上添加的事务注解不会生效,因此无法直接给两个私有方法单独配置事务传播属性。
可行解决方案(无需修改私有方法访问权限)
推荐使用编程式事务开启独立事务写入错误日志,不需要调整原有方法结构,改造成本最低:
- 首先在当前Service类中注入
TransactionTemplate实例@Autowired private TransactionTemplate transactionTemplate; - 修改catch块内的错误写入逻辑,用
TransactionTemplate指定REQUIRES_NEW传播级别开启独立事务,该事务的提交不受外层主事务回滚的影响@Transactional public void myTransactionalMethod(){ try { soSomethingAndSaveOnDB(); // private method }catch (Exception exception){ // 开启独立事务写入错误日志 transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); transactionTemplate.execute(status -> { saveSomethingOnDBWhenAnErrorOccurs(); // 原有私有方法直接调用即可 return null; }); throw exception; } }
注意事项
- 独立事务内仅执行错误日志写入逻辑,不要操作和外层主事务相同的业务数据,避免出现锁冲突或数据不一致问题
- 如果项目里多处需要类似的独立事务写入日志的场景,可以单独配置一个全局的
TransactionTemplateBean,固定设置REQUIRES_NEW传播级别,直接注入使用即可,不需要每次调用时动态设置属性 - 该方案默认适用于Spring框架环境,其他JavaEE事务框架可参照思路替换为对应框架的编程式独立事务实现
内容的提问来源于stack exchange,提问作者davioooh
相关产品推荐
相关产品推荐

