如何为TransactionTemplate配置等同于@Transactional的noRollbackFor属性?
实现方案
首先明确核心逻辑:你配置的PROPAGATION_REQUIRES_NEW已经让子事务和父事务完全隔离,子事务本身的回滚默认不会影响父事务。父事务回滚的根本原因是子事务抛出的异常未被捕获,传递到了被@Transactional标注的父方法,触发了父事务的回滚规则。
要实现和@Transactional的noRollbackFor一致的效果,分两种场景处理:
场景1:指定异常发生时,子事务不回滚,父事务也不回滚
重写TransactionTemplate的rollbackOn方法自定义子事务的回滚规则,同时外层捕获指定异常避免向上传递:
@Transactional public void foo() { bar(); } private void bar() { // 自定义TransactionTemplate,实现子事务层面的noRollbackFor TransactionTemplate transactionTemplate = new TransactionTemplate(platformTransactionManager) { @Override public boolean rollbackOn(Throwable ex) { // 匹配到指定异常时,子事务不回滚 if (ex instanceof CustomException) { return false; } // 其余异常保持默认规则:RuntimeException/Error回滚,Checked异常默认不回滚 return super.rollbackOn(ex); } }; transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); try { transactionTemplate.execute(__ -> { // 子事务业务代码 if (业务触发条件) { throw new CustomException("不需要回滚的业务异常"); } return null; }); } catch (CustomException e) { // 捕获指定异常,不向上抛给父方法,避免触发父事务回滚 // 可选:补充日志记录、业务补偿等逻辑 } }
场景2:指定异常发生时,子事务回滚,但父事务不回滚
不需要修改子事务的回滚规则,只要在调用execute的外层捕获指定异常即可:
private void bar() { TransactionTemplate transactionTemplate = new TransactionTemplate(platformTransactionManager); transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); try { transactionTemplate.execute(__ -> { // 业务代码抛出CustomException时,子事务会自动回滚 throw new CustomException("子事务回滚,父事务不回滚的异常"); }); } catch (CustomException e) { // 捕获异常不向上传递,父事务不会触发回滚 } }
补充说明
如果你需要把指定异常继续抛到父方法,同时父事务不回滚,直接在父方法的@Transactional注解上加noRollbackFor参数即可,和常规用法一致:
@Transactional(noRollbackFor = CustomException.class) public void foo() { bar(); }
内容的提问来源于stack exchange,提问作者Cube.
相关产品推荐
相关产品推荐

