这是我的问题:
我在一个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
中使用try和catch但这些都没有改变什么。
由于异常是在另一个事务中抛出且已回滚,所以我不明白为什么它不能正常工作。我查看了这个问题:Jpa transaction javax.persistence.RollbackException: Transaction marked as rollbackOnly,但它并没有真正帮助我解决问题。
我非常感激如果有人能给我一些提示。
更新:
通过在由
method2
调用的方法上设置propagation=Propagation.REQUIRES_NEW
,我使其工作起来了(实际上是发送异常的那个方法)。这个方法定义在一个与我的BatchService
非常相似的类中。所以我不明白为什么它在这个级别上可以工作,而在method2
中不能。我将
method2
设置为public,因为根据文档,在方法是private时,注释@Transactional
不起作用:“@Transactional注释可以放置在接口定义之前,在接口上的方法之前,在类定义之前或在类上的public方法之前。”
我还尝试使用Exception而不是RuntimeException(因为它更适合),但它也没有改变任何东西。
即使它正在工作,问题仍然存在,因为它有一种奇怪的行为,我想了解为什么它不能像应该那样工作。