Spring事物异常解析:UnExpectedRollbackException的起因与解决方案
2023-09-19 23:28:51
掌握 Spring 事务:避免 UnexpectedRollbackException 异常
认识 UnexpectedRollbackException
在 Spring 应用程序中,org.springframework.transaction.UnExpectedRollbackException
异常表明事务在提交后意外回滚。这通常是因为事务传播属性配置不当或异常处理不当。
理解事务传播属性
Spring 事务传播属性决定了新事务如何与调用它的当前事务交互。常见的属性包括:
PROPAGATION_REQUIRED
:如果存在事务,则加入;否则创建一个新事务。PROPAGATION_REQUIRES_NEW
:创建一个新事务,暂停当前事务。PROPAGATION_NOT_SUPPORTED
:以非事务方式执行,暂停当前事务。
UnexpectedRollbackException 的根源
UnExpectedRollbackException
通常发生在以下情况:
- 当事务传播属性设置为
PROPAGATION_REQUIRED
时,方法抛出异常。 - 事务在提交之前被标记为回滚,但提交已经发生。
解决 UnexpectedRollbackException
要避免 UnExpectedRollbackException
,可以采取以下措施:
- 正确设置传播属性: 根据业务需求选择合适的传播属性。例如,对于服务层方法,通常使用
PROPAGATION_REQUIRED
。 - 妥善处理异常: 捕获方法中的异常并进行处理。如果异常是可预期的且不需要回滚事务,可以在
catch
块中捕获并处理它,而无需抛出异常。 - 检查事务状态: 在提交事务之前,检查其状态。如果事务被标记为回滚,可以先回滚事务,然后再抛出异常。
代码示例
以下代码示例展示了如何正确设置传播属性:
@Transactional(propagation = Propagation.REQUIRED)
public void myMethod() {
// ...
}
常见问题解答
-
为什么
PROPAGATION_REQUIRED
会导致UnExpectedRollbackException
?
因为PROPAGATION_REQUIRED
要求方法在事务中执行。如果方法抛出异常,事务将被标记为回滚。 -
如何处理可预期的异常?
在catch
块中捕获可预期的异常并进行处理,而无需抛出异常。这可以避免事务回滚。 -
事务状态如何被标记为回滚?
可以通过编程方式使用TransactionStatus.setRollbackOnly()
或由于发生不可恢复的异常。 -
如何使用
TransactionStatus
检查事务状态?@Transactional public void myMethod() { TransactionStatus status = TransactionSynchronizationManager.getCurrentTransaction(); if (status.isRollbackOnly()) { // ... } // ... }
-
除了本文中讨论的措施之外,还有其他方法可以避免
UnExpectedRollbackException
吗?
是的,可以使用 AOP 切面来处理异常并控制事务回滚行为。