Ste*_*ers 3 java spring hibernate jpa transactions
我的Spring/Java Web应用程序具有@Transactional可以触及数据库的服务:
@Transactional
public class AbstractDBService { ... }
Run Code Online (Sandbox Code Playgroud)
所需的功能适用于任何未被捕获的 throwable,它会在服务层之外传播,从而导致回滚.有点惊讶这不是默认行为,但经过一些谷歌搜索后尝试:
@Transactional(rollbackFor = Exception.class)
Run Code Online (Sandbox Code Playgroud)
这似乎有效,除非故意吞下异常并且不再重新抛出异常.(特殊情况是当找不到实体时.猜测这可能会被重新设计为不会抛出异常,但期望不可避免地存在其他例子 - 例如,InterruptedException在使用时会想到一个实体Thread.sleep()).然后春天抱怨:
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)
Run Code Online (Sandbox Code Playgroud)
默认情况下,Spring不会为Error子类回滚,可能是因为一旦抛出一个错误,JVM将处于一个足够好的状态,无论如何都要对它做任何事情似乎都是值得怀疑的,此时事务可能会超时.(如果在引发OutOfMemoryError时尝试回滚,最可能的结果是另一个OutOfMemoryError.)因此,您可能无法获得太多收益.
当你提到吞下一个异常的情况时,Spring无法预料它会知道它,因为异常没有找到Spring的代理(它实现了事务功能).这就是你的RollbackException示例中发生的事情,Hibernate已经发现事务需要回滚但Spring没有得到备忘录,因为有人吃了异常.所以Spring没有回滚事务,它认为一切正常并尝试提交,但由于Hibernate标记了事务回滚,提交失败.
答案是不要吞下这些例外,而是让它们被抛出; 让它们不受控制应该会让你更容易做正确的事情.应该设置一个异常处理程序来接收从控制器抛出的异常,在应用程序的任何级别抛出的大多数异常都可以被捕获并记录.
| 归档时间: |
|
| 查看次数: |
5855 次 |
| 最近记录: |