在处理异常后,Spring嵌套事务会回滚。

7

我有一个带有@Service注解的类,其中有一个@Transactional方法,该方法调用了另一个服务上的另一个@Transactional方法。大概就是这样:

@Service
public class AService {
  @Autowired
  BService b;
  @Autowired
  ARepository aRepo;

  @Transactional
  public void methodOne(){
    try{
      b.methodTwo();
    }catch(RuntimeException e){}
    aRepo.save(new A());
  }

} 

@Service
public class BService{

    @Transactional
    public void methodTwo(){
      if(true)
        throw new RuntimeException();
    }

}

我希望可以插入实体A,但如果嵌套事务抛出异常,即使在 AService.methodOne() 处理了该异常,插入也将被拒绝。

我可以使用 @Transactional(propagation = Propagation.REQUIRES_NEW) 注释 methodTwo()。但这样会影响性能。


这里没有嵌套事务,只有一个事务。如果您想要单独的事务,则需要使用“REQUIRES_NEW”注释另一个事务。是的,这会对性能产生影响,因为它会启动一个新的事务。 - M. Deinum
这个问题还有更优雅的解决方案吗? - the-red-paintings
不行。你要么提交所有内容,要么回滚所有内容…… 你不能部分提交会破坏事务的ACID属性的东西。 - M. Deinum
如果我将try-catch块移动到methodTwo()中,将成功插入一个实体。但是在我的真实methodOne中,我有很多方法调用,其中一些对业务逻辑是必需的。 - the-red-paintings
你找到解决方案了吗?我也遇到了同样的问题。 - Vishal Patel
1个回答

1

如果您不希望在methodTwo发生异常后回滚methodOne的事务,则可以使用@Transactional(noRollbackFor = {RuntimeException.class})methodOne进行注释。但请注意,这有点棘手,请三思而后行。


methodOne() 有很多其他服务方法的调用,而这些方法的调用不仅限于AService。我希望这种行为只在AService中发生。 - the-red-paintings

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接