【问题标题】:Grails/Spring REQUIRES_NEW rolling back outer transactionGrails/Spring REQUIRES_NEW 回滚外部事务
【发布时间】:2017-11-21 23:36:36
【问题描述】:

REQUIRES_NEW 正在回滚所有事务:

我有一个标记为@Transactional(propagation = REQUIRES_NEW) 的方法 在同样具有标记为@Transactional(propagation = REQUIRED) 的方法的bean 中。这些方法从不相互调用。它们分别从另一个 bean 调用。但是,当我标记为REQUIRES_NEW 的方法失败时,它会回滚整个事务,包括标记为REQUIRED 的方法(这是有问题的)。

我的理解是,如果采用这种方式,Spring AOP 将有机会拦截REQUIRES_NEW 方法并启动新的逻辑事务。

总体思路是这样的:

@Transactional
class TransactionalBean{

     @Transactional(propagation = REQUIRED) 
     public void methodA(){ //do transactional work }

     @Transactional(propagation = REQUIRES_NEW)
     public void methodB(){ //do transactional work }
}

然后调用 bean 看起来像这样:

@Transactional
class CallingBean{
   @Autowired
   TransactionalBean

   public void doWork(){
      TransactionalBean.methodA();
      TransactionalBean.methodB(); 
   }
}

所以如果方法 A 和 B 成功,一切都很好。但是,当方法 B 失败时,方法 A 中完成的工作会回滚。我的理解是,当调用 methodB() 时,它“应该”被 AOP 拦截并开始一个新事务并暂停另一个事务,但它不起作用。我该如何解决?我正在使用 Grails 2.5、Hibernate、JPA

【问题讨论】:

  • 修复它的最佳方法是升级。 2.5 不再维护。
  • 不幸的是,这个项目我被困在 2.5 上。是框架有问题吗?

标签: spring grails


【解决方案1】:

问题在于CallingBean 被标记为@Transactional 的方式。正在发生的事情是CallingBean 正在创建一个事务,比如说t1CallingBean 正在调用两个事务方法methodA 和methodB。由于methodA需要一个事务,它将利用现有事务t1。但是,methodB 将创建一个新事务,因为注释需要一个新事务,比如t2。 methodA 的事务边界不会在控件退出 methodA 时结束,而是一直保持活动状态,直到 methodB 完成为止,因为事务在调用 bean 处开始。现在事务t2 在方法B 中失败了,异常会冒泡到调用bean 并且事务t1 会失败。

为了解决此问题,您可以根据需要执行以下操作之一。

关闭CallingBean 类中的@Transactional 注释。

//@Transactional
class CallingBean{
...
}

更新注解以使用noRollbackFor 选项

@Transactional(noRollbackFor={WhateverException.class})
class CallingBean{
...
}

【讨论】:

    猜你喜欢
    • 2012-10-14
    • 2019-01-21
    • 2012-09-25
    • 1970-01-01
    • 2020-06-12
    • 2021-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多