首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >@Transactional(propagation=Propagation.REQUIRES_NEW)的奇怪行为

@Transactional(propagation=Propagation.REQUIRES_NEW)的奇怪行为
EN

Stack Overflow用户
提问于 2013-04-02 15:20:34
回答 1查看 25.7K关注 0票数 19

这里是我的问题:

我正在Java /Spring/Hibernate应用程序上运行一个批处理。这个批处理调用一个method1。这个方法调用一个method2,它可以抛出UserException (扩展RuntimeException的类)。以下是它的样子:

代码语言:javascript
复制
@Transactional
public class BatchService implements IBatchService {
 @Transactional(propagation=Propagation.REQUIRES_NEW)
 public User method2(User user) {
   // Processing, which can throw a RuntimeException
 }

 public void method1() {
   // ...
   try {
     this.method2(user);
   } catch (UserException e) {
     // ...
   }
   // ...
 }
}

当执行继续时,异常会被捕获,但是在method1结束时,当事务关闭时,会抛出一个RollbackException。

这里是堆栈跟踪:

代码语言:javascript
复制
org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Transaction marked as rollbackOnly
    at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:476)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:393)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:120)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy128.method1(Unknown Source)
at batch.BatchController.method1(BatchController.java:202)

method2没有抛出此异常时,它工作得很好。

我尝试过的:

  • @Transactional(noRollbackFor={UserException.class}))上设置method1
  • 尝试在method2中捕获

但这并没有改变什么。

由于异常是在发生回滚的另一个事务中抛出的,所以我不明白为什么它不能工作。我看了一下这个:Jpa transaction javax.persistence.RollbackException: Transaction marked as rollbackOnly,但它并没有真正帮助我。

如果有人能给我线索,我会很高兴的。

更新

我通过对由propagation=Propagation.REQUIRES_NEW调用的方法(实际上是发送异常的方法)设置method2来使其工作。这个方法是在一个与我的BatchService非常相似的类中定义的。因此,我不明白为什么它在这个级别上工作,而不是在method2上工作。

  • 我已经将method2设置为公共的,因为如果该方法是私有的,则不考虑注释@Transactional,如文档中所述:

@Transactional注释可以放在接口定义、接口上的方法、类定义或类上的公共方法之前。

  • 我也尝试使用Exception而不是RuntimeException (因为它更合适),但它也没有改变任何东西。

即使它正在运作,问题仍然是开放的,因为它有一种奇怪的行为,我想理解为什么它的行为不应该是这样的。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-04-02 16:32:26

缺省情况下,Spring事务通过使用代理包装Spring来处理事务和异常。当您从method2()调用method1()时,您完全绕过了这个代理,因此它无法启动一个新事务,并且您实际上是从调用method1()打开的事务中调用method2()

相反,当您从method1()调用另一个注入bean的方法时,实际上是在事务代理上调用一个方法。因此,如果这个外星方法被标记为REQUIRES_NEW,代理将启动一个新事务,并且您可以在method1()中捕获异常并继续外部事务。

这在the documentation中有描述。

票数 41
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15767914

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档