2017-06-19 71 views
1

REQUIRES_NEW被回滚所有交易:Grails的/春REQUIRES_NEW回滚外部事务

我有一个方法,一个bean也有一些方法标记@Transactional(propagation = REQUIRED)内标@Transactional(propagation = REQUIRES_NEW) 。这些方法从不互相呼叫。它们是从另一个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 } 
} 

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

@Transactional 
class CallingBean{ 
    @Autowired 
    TransactionalBean 

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

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

+0

最好的办法来解决它是升级。 2.5不再维护。 –

+0

不幸的是,我被困在这个项目的2.5上。这是框架问题吗? – dirtbiker

回答

0

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

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

关闭CallingBean类中的@Transactional注释。

//@Transactional 
class CallingBean{ 
... 
} 

更新注释使用noRollbackFor选项

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