开发中突然出现错误:
org.springframework.transaction.IllegalTransactionStateException: Transaction is already completed - do not call commit or rollback more than once per transaction
at org.springframework.transaction.support.AbstractPlatformTransactionManager.rollback(AbstractPlatformTransactionManager.java:829)
at com.longfor.longjian.evaluation.app.service.impl.QualityAppealServiceImpl.xTaskApprovalSubmitSubmit(QualityAppealServiceImpl.java:505)
at com.longfor.longjian.evaluation.app.service.impl.QualityAppealServiceImpl
实在莫名其妙,初步分析是由于事物完成之后又进行了commit,rollback操作。通过查看代码方法嵌套调用,而两个方法都有事物。
例如:方法A调用B方法,A和B中都有事物,这就应用到了spring事物传播。
问题原因
找到事物传播几种类型,发现spring默认将嵌套事物进行合并,通过断点观察我的B方法进行了rollback操作,而A方法进行了commit操作,rollback使本事物已经完成,不能进行commit操作。这就导致了上面的问题。
解决方法
解决方法需要将两个事物进行分开,不合并。可以使用PROPAGATION_REQUIRES_NEW或PROPAGATION_NESTED,
PROPAGATION_REQUIRES_NEW
1.运行到子事物是重新创建一个事物
2.子事物是否回滚不影响父级事物
3.父级事物是否回滚不影响子事物
PROPAGATION_NESTED(黄色为区别)
1.运行到子事物是重新创建一个事物
2.子事物是否回滚不影响父级事物
3.父级事物回滚子事物也回滚
代码
// A code block
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_NESTED);
TransactionStatus status = txManager.getTransaction(definition);
当然spring还有其他几种传播模式,我的业务中使用的是PROPAGATION_NESTED这种,其他几种可以参考链接: Spring事务传播模式.