繁体   English   中英

如何使Spring @Transactional回滚所有未捕获的异常?

[英]How to make Spring @Transactional roll back on all uncaught exceptions?

我的Spring / Java Web应用程序具有可以触及数据库的@Transactional服务:

@Transactional
public class AbstractDBService  { ... }

所需的功能适用于任何未被捕获的 throwable,它会在服务层之外传播,从而导致回滚。 有点惊讶这不是默认行为,但经过一些谷歌搜索后尝试:

@Transactional(rollbackFor = Exception.class)

这似乎有效,除非故意吞下异常并且不再重新抛出异常。 (具体情况是当找不到实体时。猜测这可能会被重新设计为不抛出异常但期望不可避免地存在其他异常 - 例如,当使用Thread.sleep()时,一个想到的是InterruptedException 然后春天抱怨:

org.springframework.transaction.TransactionSystemException:无法提交JPA事务; 嵌套异常是javax.persistence.RollbackException:事务标记为rollbackOnly ... truncated ..引起:javax.persistence.RollbackException:在org.hibernate.jpa.internal.TransactionImpl.commit上标记为rollbackOnly的事务(TransactionImpl.java:58 )org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:517)

我在这里错过了什么吗?...有没有办法告诉Spring回滚所有未被捕获的扔掉的东西

如果要回滚所有未捕获的Throwable,可以在注释中指定:

@Transactional(rollbackFor = Throwable.class)

默认情况下,Spring不会为Error子类回滚,可能是因为一旦抛出一个错误,JVM将处于一个足够好的状态,无论如何都要对它做任何事情似乎都是值得怀疑的,此时事务可能会超时。 (如果在引发OutOfMemoryError时尝试回滚,最可能的结果是另一个OutOfMemoryError。)因此,您可能无法获得太多收益。

当你提到吞下一个异常的情况时,Spring不可能知道它,因为异常没有找到Spring的代理(它实现了事务功能)。 这就是你的RollbackException示例中发生的事情,Hibernate已经发现事务需要回滚但是Spring没有得到备忘录,因为有人吃了这个例外。 所以Spring没有回滚事务,它认为一切正常并尝试提交,但由于Hibernate标记了事务回滚,提交失败。

答案是不要吞下这些例外,而是让它们被抛出; 让它们不受控制应该会让你更容易做正确的事情。 应该设置一个异常处理程序来接收从控制器抛出的异常,在应用程序的任何级别抛出的大多数异常都可以被捕获并记录。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM