这是我的问题:
我正在Java EE / Spring / Hibernate应用程序上运行批处理。此批次称为method1。此方法调用method2可以抛出的UserExceptiona(一个扩展类RuntimeException)。看起来是这样的:
method1
method2
UserExceptiona
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不抛出此异常时,它将很好地工作。
我尝试过的
@Transactional(noRollbackFor={UserException.class}))上method1
由于异常发生在发生回滚的不同事务中,所以我不明白为什么它不起作用。我看了一下:Jpa事务javax.persistence.RollbackException:事务标记为rollbackOnly,但它并没有真正帮助我。
如果有人可以给我一个线索,我将非常感激。
我通过设置propagation=Propagation.REQUIRES_NEW调用方法method2(实际上是发送异常的方法)来使其工作。此方法在与my非常相似的类中定义BatchService。所以我不明白为什么它可以在这个级别而不是在这个级别上工作method2。
propagation=Propagation.REQUIRES_NEW
@Transactional
@Transactional批注可以放在接口定义,接口上的方法,类定义或类上的公共方法之前。
Exception
默认情况下,Spring事务通过使用代理处理Spring Bean来工作,该代理处理事务和异常。method2()从调用时method1(),你将完全绕过该代理,因此它无法启动新事务,并且实际上是method2()从与调用打开的事务相同的事务中进行调用method1()。
method2()
method1()
相反,当你从中调用另一个注入的bean method1()的方法时,实际上是在事务代理上调用方法。因此,如果此外来方法用REQUIRES_NEW标记,则代理将启动新事务,并且你可以捕获异常method1()并恢复外部事务。