这是我的问题:
我正在Java EE / Spring / Hibernate应用程序上运行批处理。此批次称为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
method2
由于异常发生在发生回滚的不同事务中,所以我不明白为什么它不起作用。我看了一下:Jpa事务javax.persistence.RollbackException:事务标记为rollbackOnly,但它并没有真正帮助我。
如果有人可以给我一个线索,我将非常感激。
我通过设置propagation=Propagation.REQUIRES_NEW
调用方法method2(实际上是发送异常的方法)来使其工作。此方法在与my非常相似的类中定义BatchService。所以我不明白为什么它可以在这个级别而不是在这个级别上工作method2。
method2
为public,因为@Transactional
如果该方法是私有的,则不考虑注释,如文档中所述:
@Transactional
批注可以放在接口定义,接口上的方法,类定义或类上的公共方法之前。
Exception
代替RuntimeException
(因为它更合适),但是它也没有改变任何东西。默认情况下,Spring事务通过使用代理处理Spring Bean来工作,该代理处理事务和异常。method2()
从调用时method1()
,你将完全绕过该代理,因此它无法启动新事务,并且实际上是method2()从与调用打开的事务相同的事务中进行调用method1()
。
相反,当你从中调用另一个注入的bean method1()
的方法时,实际上是在事务代理上调用方法。因此,如果此外来方法用REQUIRES_NEW标记,则代理将启动新事务,并且你可以捕获异常method1()
并恢复外部事务。
问题内容: 如果有人可以解释此注释的作用以及确切的使用时间: 谢谢 问题答案: 当传播设置为PROPAGATION_REQUIRED时,将为应用该设置的每种方法创建一个逻辑事务作用域。每个此类逻辑事务作用域可以单独确定仅回滚状态,而外部事务作用域在逻辑上与内部事务作用域无关。当然,在标准PROPAGATION_REQUIRED行为的情况下,所有这些范围都将映射到同一物理事务。因此,内部事务范围中设
问题内容: 有人可以通过实际示例解释注释中的隔离和传播参数吗? 基本上,何时和为什么我应该选择更改其默认值。 问题答案: 好的问题,尽管不是一个简单的答案。 Propagation 定义事务之间的关系。常用选项: :代码将始终在事务中运行。创建一个新事务或重用一个事务(如果有)。 :代码将始终在新事务中运行。如果存在当前事务,则将其挂起。 Isolation 定义事务之间的数据契约。 :允许脏读。
我想问一下这种行为的原因,因为在运行Spring方法/类时,我似乎不完全理解Hibernate中的和之间的区别。 下面的代码应该回滚DB操作,但它没有回滚(整个类注释为): 以下代码在引发异常时按预期回滚: save()方法来自类,因此它的代码是: 该实体是一个已存在的实体,因此我理解它正在执行。根据JPA规范: find方法(前提是在没有锁的情况下调用它或使用LockModeType.None调
有两个代码片段。 在第一个例子中,我们从总是引发一些异常的任务中创建CompletableFuture。然后我们将“例外”方法应用于该未来,然后是“接受”方法。我们不会将Accept方法返回的新future分配给任何变量。然后我们对原始未来调用“join”。我们看到的是,“异常”方法以及“thenAccept”都已被调用。我们看到它是因为他们在输出中打印了适当的行。但“异常”方法并没有抑制该异常。