@Transactional 注解rollbackFor 范围问题以及同一个类方法之间调用事务问题
spring Transactional 注解rollbackFor 范围问题
我们首先看下面一组代码
代码1
@Transactional public String testInnerInvodeTransactional(Integer id) throws Exception { testMapper.deleteById(id); if(true){ throw new RuntimeException("测试异常"); } return "SUCCESS"; }
代码2
@Transactional public String testInnerInvodeTransactional(Integer id) throws Exception { testMapper.deleteById(id); if(true){ throw new Exception("测试异常"); } return "SUCCESS"; }
原数据库数据如下
代码1 执行结果
代码2 执行结果
两个代码主要区别是抛出异常一个是RuntimeException ,一个是Exception,可以看出代码1回滚了而代码2没有回滚,为什么呢
spring Transactional 的rollbackFor 原理
spring Transactional 的rollbackFor 原理
spring Transactional 默认的rollbackFor 范围是UncheckExcetion ,也就是RuntimeException和Error
代码1 我们抛出的是RuntimeException在默认范围内
代码2 我们抛出的是Exception 属于父类excetion 并不是默认范围,因此没有回滚
一定要设置spring Transactional 的rollbackFor 范围
比如可以直接设置为Exception.class,同时进来设置好传播范围,参考如下设置:
解决方案:
@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
spring 同一个类方法之间调用事务问题
我们看下面一组代码
代码1
/** * 外层方法处理数据 * */ public String testInnerInvodeTransactional(Integer id) throws Exception { //内层方法处理数据 innerInvodeTransactional(id); return "SUCCESS"; } @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED) public void innerInvodeTransactional(Integer id) { testMapper.deleteById(id); if(true){ throw new RuntimeException("测试异常"); } }
代码2
/** * 外层方法处理数据 * */ @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED) public String testInnerInvodeTransactional(Integer id) throws Exception { //内层方法处理数据 innerInvodeTransactional(id); return "SUCCESS"; } public void innerInvodeTransactional(Integer id) { testMapper.deleteById(id); if(true){ throw new RuntimeException("测试异常"); } }
原数据库数据如下
代码1执行结果
代码2执行结果
上面两个方法的主要区别在于Transactional放在了入口类还是被调用类, 可以看出代码1没有回滚,而代码2回滚了,为什么呢
spring Transactional 原理
spring 会扫描带@Transactional 的方法,然后形成aop代理,执行以下流程
1.代理类会设置事务为手动提交
2.try ,catch 住要执行的方法
3.如果抛出异常,则执行catch 内的回滚代码
4.如果正常执行,则finally 中提交事务
解决方案:
由以上可以内部方法调用问题主要在于否执行时执行的是aop代理类
如果是代理类,则会执行事务回滚
如果不是代理类,则不会执行事务回滚
所以入口的方法一定要加上事务注解,不然不会生成aop代理也就不会执行回滚操作
相关文章
- 如何把设备安全的接入AWS IoT(一)
- 浅谈AWS CloudFront在特殊场景下的配置和错误处理
- python MapReduce单词统计
- 使用 AWS Lambda 和 AWS Greengrass 在边缘站点进行协议转换
- 托管 Spot 训练:最高可节省 90% 的 Amazon SageMaker 训练作业成本
- Direct Connect A/B段双活实现
- 使用 AWS IoT 服务进行资产状况监控
- 使用 AWS IoT Core 即时预配置
- 利用 Amazon S3 inventory, Amazon EMR, 和 Amazon Athena 来触发针对预先存在的对象的跨区域复制
- linux安装opencv-python
- 通过 Amazon EMR 重新配置动态修改集群
- 新增功能 — 触发内核错误以诊断 EC2 实例无响应的问题
- Amplify 控制台 — 托管全堆栈式无服务器 Web 应用程序
- 将网络负载均衡器与 Amazon EKS 上的 NGINX 入口控制器配合使用
- 使用 Amazon Kinesis Data Firehose 和 Amazon EMR 中的 Apache Spark 优化流式数据处理
- 通过 Amazon EMR 重新配置动态修改集群
- 新版 AWS Tools for PowerShell 的预览版
- 借助 AWS Step Functions 将回调 URL 用于批准电子邮件
- 认证授权专题(一) : Cognito, OIDC 实现 S3 精细化权限控制
- 认证授权专题(二) : AWS STS, OpenID Connect 实现 S3 精细化权限控制