关于do not call commit or rollback more than once per transaction报错的分析
错误日志
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:804) ~[spring-tx-5.3.12.jar:5.3.12]
at com.cxstar.business.service.impl.EBookCollectionServiceImpl.delete(EBookCollectionServiceImpl.java:304) ~[classes/:na]
at com.cxstar.api.business.controller.collection.EBookCollectionController.delete(EBookCollectionController.java:105) ~[classes/:na]
at com.cxstar.api.business.controller.collection.EBookCollectionController$$FastClassBySpringCGLIB$$5a53a40a.invoke(<generated>) ~[classes/:na]
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.12.jar:5.3.12]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:783) ~[spring-aop-5.3.12.jar:5.3.12]
问题分析:
该报错信息的意思是:每个事务调用提交或回滚的次数不要超过一次,在try-catch捕捉到异常进行rollback之后,又执行了finally的commit的方法
报错场景
常见的代码错误如下:
try{
//业务代码,执行增改查
}catch ( Exception e){
transactionManager.rollback(transactionStatus);
}finally {
transactionManager.commit(transactionStatus);
}
如果业务代码中报错,就会被catch捕捉到并且执行事务回滚,但是最后又执行finally的commit的方法,才会导致此问题的发生
解决方案
1.执行rollback之后,直接抛异常退出当前执行的方法
try{
//业务代码,执行增改查
}catch ( Exception e){
transactionManager.rollback(transactionStatus);
throw new BusinessException(e.getMessage());
}finally {
transactionManager.commit(transactionStatus);
}
2.去除finally,把事务提交的commit方法放到catch之前
try{
//业务代码,执行增改查
transactionManager.commit(transactionStatus);
}catch ( Exception e){
transactionManager.rollback(transactionStatus);
throw new BusinessException(e.getMessage());
}