【Spring】21、用spring目标对象处理Transaction rolled back because it has been marked as rollback-only
来源:互联网 发布:qq文件夹删除数据恢复 编辑:程序博客网 时间:2024/06/09 23:12
在使用spring做事务管理时,很多人都会遇到这样一段异常:
org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:718) at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:475) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:270) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:96) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:260) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94)
出现上面问题的场景类似下面代码这样:
ITestAService:
package com.gigamore.platform.ac.service; import com.onlyou.framework.exception.BusinessException; public interface ITestAService { void testA() throws BusinessException; }
TestAService:
package com.gigamore.platform.ac.service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import com.gigamore.platform.base.service.impl.BaseServiceImpl; import com.onlyou.framework.exception.BusinessException; @Service public class TestAService extends BaseServiceImpl implements ITestAService{ @Autowired private TestBService testBService; @Transactional public void testA(){ try{ testBService.testB(); }catch(BusinessException e){ logger.info(e.getMessage()); }catch(Exception e){ logger.info(e.getMessage()); } } }
TestBService:
package com.gigamore.platform.ac.service; import java.util.Date; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import com.gigamore.platform.ac.entity.LoanProjectEntity; import com.gigamore.platform.base.service.impl.BaseServiceImpl; import com.onlyou.framework.exception.BusinessException; @Service public class TestBService extends BaseServiceImpl{ @Transactional public void testB(){ LoanProjectEntity project = this.selectByPrimaryKey(LoanProjectEntity.class, "2c9483e748321d4601485e1714d31412"); project.setUpdDataTm(new Date()); this.update(project); throw new BusinessException("抛异常"); } }
测试用例:
@Autowired private ITestAService testAService; @Test public void testA() { testAService.testA(); }
testAService调用testBService的testB()方法,testB()方法里抛了一个BusinessException异常,但是testAService用try{}catch{}捕获异常并不往上层抛了。
看起来好像没什么问题,异常被捕获了。其实不然,在testAService调用testBService的testB()方法时,会经过一次spring事务控制切面,事务切面里本身会对testBService的testB()方法进行异常捕获: TransactionAspectSupport.invokeWithinTransaction
if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) { // Standard transaction demarcation with getTransaction and commit/rollback calls. TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification); Object retVal = null; try { // This is an around advice: Invoke the next interceptor in the chain. // This will normally result in a target object being invoked. retVal = invocation.proceedWithInvocation(); } catch (Throwable ex) { // target invocation exception completeTransactionAfterThrowing(txInfo, ex); throw ex; } finally { cleanupTransactionInfo(txInfo); } commitTransactionAfterReturning(txInfo); return retVal; }
completeTransactionAfterThrowing(txInfo, ex)里面做了txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus()),事务管理器做rollback, 把事务设置成rollback-only。 以上是testBService外层包装的事务切面做的事情。当testAService的testA()方法执行完,此时执行到testAService外层包装的事务切面,由于testA()方法执行过程没有抛出异常,所以事务正常提交,即执行的是commitTransactionAfterReturning(txInfo),事务对象txInfo对应的事务管理器进行提交事务,但事务已被设置为rollback-only,故spring对外抛出了Transaction rolled back because it has been marked as rollback-only异常。
解决办法:把TestBService的testB()方法的事务注解改成@Transactional(propagation = Propagation.NESTED),确实可以达到避免异常的效果。
- 【Spring】21、用spring目标对象处理Transaction rolled back because it has been marked as rollback-only
- spring事务 Transaction rolled back because it has been marked as rollback-only
- Transaction rolled back because it has been marked as rollback-only
- Transaction rolled back because it has been marked as rollback-only
- Transaction rolled back because it has been marked as rollback-only
- Transaction rolled back because it has been marked as rollback-only
- Transaction rolled back because it has been marked as rollback-only
- UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only
- Transaction rolled back because it has been marked as rollback-only
- Transaction rolled back because it has been marked as rollback only
- Transaction rolled back because it has been marked as rollback-only”
- “Transaction rolled back because it has been marked as rollback-only”
- Srping Transaction rolled back because it has been marked as rollback-only解决方案
- Transaction rolled back because it has been marked as rollback-only
- Transaction rolled back because it has been marked as rollback-only
- “Transaction rolled back because it has been marked as rollback-only”
- Transaction rolled back because it has been marked as rollback-only”
- Transaction rolled back because it has been marked as rollback-only
- spark原理架构
- 一键运行R脚本
- idea 使用 PlantUML 写程序流程图
- 行列均递增的二维数组中查找元素
- netcat教程
- 【Spring】21、用spring目标对象处理Transaction rolled back because it has been marked as rollback-only
- 案例观察丨如何及时发现公司运作中的不正常行为?
- nginx可视化配置设置
- 线程 -----基础
- Spring注解的实现原理
- [bzoj3527]&[caioj1451][FFT]多项式
- 访问修饰符的修饰权限
- 机器学习算法总结--K均值算法
- android应用数据清除管理器