java - @Transactional(propagation=Propagation.REQU

这是我的问题:

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

@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。

这是堆栈跟踪:

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没有抛出这个异常时,它运行良好。

我尝试过的:

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

但这并没有改变任何东西。

由于异常是在发生回滚的不同事务中引发的,我不明白为什么它不起作用。我看过这个:Jpa transaction javax.persistence.RollbackException: Transaction marked as rollbackOnly但它并没有真正帮助我。

如果有人能给我一个线索,我将非常感激。

更新

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

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

The @Transactional annotation may be placed before an interface definition, a method on an interface, a class definition, or a public method on a class.

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

即使它正在工作,问题仍然悬而未决,因为它有一种奇怪的行为,我想了解为什么它的行为不像它应该的那样。

最佳答案

默认情况下,Spring 事务通过使用处理事务和异常的代理包装 Spring bean 来工作。当你从 method1() 调用 method2() 时,你完全绕过了这个代理,所以它不能开始一个新的事务,你实际上是在调用 method2() 来自与调用 method1() 所打开的事务相同的事务。

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

这在 the documentation 中有描述.

关于java - @Transactional(propagation=Propagation.REQUIRES_NEW) 的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15767914/

相关文章:

spring - 如果我忘记将 Spring SessionStatus 标记为 "Complete

spring - Java EE 和 Spring 框架的区别

spring - 如何在 Spring Boot 中为文件上传指定临时目录?

java - Spring根应用上下文和servlet上下文混淆

java - Spring/Hibernate 测试 : Inserting test data a

java - Spring Security Configuration @Order 不是唯一异常

java - 处理一个 Spring bean/接口(interface)的多个实现

java - @Cacheable 命中的 Spring 缓存日志记录

spring - 创建 ServletContext 资源中定义的名称为 'org.springfr

java - 从 4.2.0.RC3 升级到 4.2.0.RELEASE 时出现 Spring As