使用TransactionManager能否实现事务嵌套?TransactionTemplate+REQUIRES_NEW配置问题
当前实现存在的问题
someMethod()没有配置任何事务传播规则,当前默认会加入process()方法中TransactionTemplate开启的REQUIRES_NEW事务,没有独立事务。如果process()调用someMethod()之后的逻辑抛出异常,service.save()的操作会随外层事务一起回滚,完全不满足要求的「无论外层是否正常都独立提交」的需求。- 如果直接将外层事务查询出来的
SomeEntity实体传入someMethod()保存,一旦someMethod()开启独立新事务,外层事务的持久化上下文和新事务不绑定,直接传入游离态的实体调用save,可能会出现非预期的更新、或者游离实体相关异常。
调整方案
第一步:给someMethod()配置独立的REQUIRES_NEW事务
两种实现方式可按需选择:
方案1:用@Transactional注解配置(代码更简洁,推荐)
仅在otherBean的someMethod()上添加事务注解,process()保持现有TransactionTemplate写法即可,不会触发之前的懒加载异常:
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class) public void someMethod(SomeEntity entity) { // 先重新查询获得当前事务托管的实体,避免游离实体问题 SomeEntity managedEntity = service.findById(entity.getId()); // 执行对应的属性修改逻辑 service.save(managedEntity); }
之前
process()加@Transactional出现懒加载异常的原因大概率是注解未生效:比如方法非public、注解加在final方法上、或者Bean没有被Spring代理。而TransactionTemplate是编程式事务,只要注入的TransactionManager正确,就一定会开启事务绑定持久化上下文,所以懒加载能正常工作,该写法可以保留。
方案2:someMethod()也用TransactionTemplate编程式事务
如果不想用声明式注解,也可以在someMethod()内部同样用编程式事务开启独立事务:
@Autowired private TransactionManager transactionManager; public void someMethod(SomeEntity entity) { TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager); transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); transactionTemplate.executeWithoutResult(status -> { SomeEntity managedEntity = service.findById(entity.getId()); // 执行属性修改逻辑 service.save(managedEntity); }); }
第二步:验证配置有效性
- 确保
otherBean是Spring容器注入的实例,不是手动new出来的对象,否则声明式事务注解会失效。 - 如果使用方案1,确认项目已经开启事务管理(SpringBoot默认开启,只要引入spring-tx依赖或者加了
@EnableTransactionManagement注解即可)。
内容的提问来源于stack exchange,提问作者Lucas F.
相关产品推荐
相关产品推荐

