【Spring】21、用spring目标对象处理Transaction rolled back because it has been marked as rollback-only
在使用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
原文地址:https://blog.csdn.net/f641385712/article/details/80445912 1.概述 想必大家一想到事务,就想到ACID,或者也会想到CAP.但笔者今 ...
- Spring事务嵌套引发的问题--Transaction rolled back because it has been marked as rollback-only
转载https://blog.csdn.net/f641385712/article/details/80445912 读了两边才找到问题
- “Transaction rolled back because it has been marked as rollback-only”
spring的声明事务提供了强大功能,让我们把业务关注和非业务关注的东西又分离开了.好东西的使用,总是需要有代价的.使用声明事务的时候,一 个不小心经常会碰到“Transaction rolled b ...
- Transaction rolled back because it has been marked as rollback-only
出现这种错误的原因 1.接口A 调用了接口B 2.接口B报异常了,没有在B里面进行try catch捕获 3.接口A对 接口B进行了try catch捕获 因为接口B报异常 会把当前事物A接口的事物( ...
- Transaction rolled back because it has been marked as rollback-only分析解决方法
1. Transaction rolled back because it has been marked as rollback-only事务已回滚,因为它被标记成了只回滚<prop key= ...
- 【springcloud】Transaction rolled back because it has been marked as rollback-only
问题: 一个ajax请求,发生系统错误,错误内容:Transaction rolled back because it has been marked as rollback-only 原因是调用的s ...
- Transaction rolled back because it has been marked as rollback-only 原因 和解决方案
产生原因 , 1 serviceA 调用 serviceB 然后 B 抛出异常 ,B 所在的 事物 回滚,B 把当前可写 事物标记成 只读事物 , 2 如果 A 和B 是在 同一个事物环境,并且 ...
- 记一次org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only异常
@Transactional(rollbackFor = Exception.class) @Overridepublic DubboResult<Boolean> productAddO ...
- springboot成神之——spring boot,spring jdbc和spring transaction的使用
本文介绍spring boot,spring jdbc和spring transaction的使用 项目结构 依赖 application model层 mapper层 dao层 exception层 ...
随机推荐
- linux之配置Mongodb~
OK 让我们先下载一波mongodb~(64位ubuntu) curl -O https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.0. ...
- 《HTTP权威指南》5-Web服务器
各种形状,风格,尺寸的Web服务器 Web服务器会对HTTP请求进行处理并提供响应.Web服务器有着不同的风格,形状和尺寸但是不管功能,外貌,风格有何差异,所有的Web服务器都能够接收请求资源的HTT ...
- SQL Server 2008 安装(lpt亲测)
SQL Server安装真的遇到好多问题啊!! 于是就决定写个备忘,方便自己也方便别人. 1.下载安装包 2.打开安装包,就遇到了restart computer 那里failed的错误,导致无法继 ...
- 【webpack】-- 入门与解析
每次学新东西总感觉自己是不是变笨了,看了几个博客,试着试着就跑不下去,无奈只有去看官方文档. webpack是基于node的.先安装最新的node. 1.初始化 安装node后,新建一个目录,比如ht ...
- UglifyJs打包压缩问题引起的思考
问题背景 最近做了一个webapp项目,qa用手机测试功能时,在iphone6plus上表现是白屏,其他手机目测是ok的:因为之前在测试其他项目时也发现在这个iphone6上表现与其他手机不太一样.于 ...
- 64位 windows10,MYSQL8.0.13重置密码(忘记密码或者无法登录)
上一节的MySQL的配置安装里,并没有用到配置文件my.ini.那在MYSQL8.0.13如何解决密码重置问题呢.我去网上搜了好多的资料都是改配置文件my.ini的,后来终于找到了一条命令:操作步骤如 ...
- 「HNOI2016」数据结构大毒瘤
真是 \(6\) 道数据结构毒瘤... 开始口胡各种做法... 「HNOI2016」网络 整体二分+树状数组. 开始想了一个大常数 \(O(n\log^2 n)\) 做法,然后就被卡掉了... 发现直 ...
- 每天学点SpringCloud(十一):Hystrix仪表盘
在SpringCloud学习系列博客第六篇文章中,我们已经学习了Hystrix的使用,但是那篇文章中有一点遗漏没有讲,那就是Hystrix Dashboard ,它可以实时的监控Hystrix的运行情 ...
- JDK 在 Linux 上安装的详细过程
1.下载JDK Linux上一般会安装Open JDK,如果有系统预装了OpenJDK的话需要先卸载掉OpenJDK, 卸载过程可以参考这里:https://www.cnblogs.com/sxdcg ...
- 微信小程序实现标签页滑块效果
微信小程序实现标签页滑块效果 小程序完整代码: wxml: <view class="swiper-tab"> <view class="swiper- ...