4

我有一个应用程序通过 jpa 对各种数据库表进行大量写入。其中一项写入可能会导致乐观锁异常。如果抛出一个,这没什么大不了的,我希望其余的事务提交。

我通过以下方式查看了 spring 事务的不回滚功能:

<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
    <constructor-arg ref="transactionManager"/>
    <constructor-arg ref="ignoreOptimisticLockingExceptionRule"/>
</bean>
<bean id="ignoreOptimisticLockingExceptionRule" class="org.springframework.transaction.interceptor.RuleBasedTransactionAttribute">
    <property name="rollbackRules">
        <list>
            <bean class="org.springframework.transaction.interceptor.NoRollbackRuleAttribute">
                <constructor-arg value="javax.persistence.OptimisticLockException"/>
            </bean>
        </list>
    </property>
</bean>
<bean class="org.springframework.orm.jpa.JpaTransactionManager"
    id="transactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

我的应用程序在将引发此异常的实体的合并方法周围捕获 OLException,但事务仍会回滚。我做了一些挖掘以查看发生了什么,并且在 JpaTransactionManager 的 doCommit 方法中 javax.persistence.RollbackException: Transactionmarked as rollbackOnly 被抛出。它被抛出是因为 rollbackOnly 标志(在 TransactionImpl 中)被标记为真。

深入研究,我看到 AbstractEntityMangerImpl 中的 merge 方法最终将事务标记为 rollbackonly,然后进一步触发异常。不过,我看不到 RuleBasedTransactionAttributes 的应用位置。我不知道我是否正确设置了该设置。

谢谢!

4

1 回答 1

4

JPA 规范要求在发生 OptimisticLockException 时将事务标记为回滚。而且我不知道您使用哪个 JPA 引擎,但至少对于 Hibernate(我希望其他引擎也一样),文档说:

如果 Session 抛出异常,包括任何 SQLException,立即回滚数据库事务,调用 Session.close() 并丢弃 Session 实例。Session 的某些方法不会使会话保持一致状态。Hibernate 抛出的任何异常都不能被视为可恢复的。通过在 finally 块中调用 close() 确保 Session 将被关闭。

所以如果你遇到这样的异常,你最好的办法是让事务回滚,然后重试。

于 2012-07-10T17:58:25.047 回答