Spring事务失效 -方法内部调用
首先感谢网友的文章
Spring事务失效的2种情况
JDK动态代理给Spring事务埋下的坑
前提知识: 两个前提
1 注解使用 spring容器的事务管理注解
@org.springframework.transaction.annotation.Transactional
2.方法开启了事务注解之后,需要异常的触发,
如果在方法内部捕获了异常,即使你开启了事务,也是没法事务回滚的
错误的使用:下面这种捕获了异常 , saveEmployee 方法里面的即使有事务,也是不会回滚的
@Transactional() //开启事务,捕获了异常,没法触发,所以有注解也没作用
public void save(){// 捕获了异常,没法触发,所以有注解也没作用try { // 捕获了异常,没法触发,所以有注解也没作用 this.saveEmployee(); }catch (Exception e){e.printStackTrace();}
}@Transactional()
public void saveEmployee(){Employee employee = new Employee();employee.setName("zhangsan");employee.setAge("26";employeeDao.save(employee);throw new RuntimeException();
}
写作背景:
我们平时在java开发中经常使用的是 Spring 的事务回滚,而且我们大多数情况下都是使用注解为主的,最近工作中,方法内部调用,事务没有起效,走了一些弯路,今天来总结一下.
方法内部调用是指: 同一个类,两个方法, 外层方法( 暂且叫 A 方法 )调用内层方法(B 方法)
使用默认的事务处理方式
因为在java的设计中,它认为不继承RuntimeException的异常是”checkException”或普通异常,如IOException,这些异常在java语法中是要求强制处理的。
对于这些普通异常,spring默认它们都已经处理,所以默认不回滚。
可以添加rollbackfor=Exception.class来表示所有的Exception都回滚。
内部调用
不带事务的方法调用该类中带事务的方法,不会回滚。因为spring的回滚是用过代理模式生成的,如果是一个不带事务的方法调用该类的带事务的方法,直接通过this.xxx()调用,而不生成代理事务,所以事务不起作用。常见解决方法,拆类。
内部调用没有发生我们期待中的事务回滚:**
spring中在一个拥有事务的方法A中调用另一个会挂起事务并创建新事务的方法B,
如果使用this调用这个方法B, 此时方法B抛出了一个异常,
此时的方法B的事务会失效的。并不会回滚。**
代码如下:
@Service
public class EmployeeService {@Autowiredprivate EmployeeDao employeeDao;public void save(){try { //此处this调用不会开启事务,数据会被保存this.saveEmployee(); }catch (Exception e){e.printStackTrace();}}@Transactional()public void saveEmployee(){Employee employee = new Employee();employee.setName("zhangsan");employee.setAge("26";employeeDao.save(employee);throw new RuntimeException();}
}
问题原因: JDK的动态代理
JDK的动态代理。只有被动态代理直接调用时才会产生事务。
在SpringIoC容器中返回的调用的对象是代理对象而不是真实的对象。
而这里的this是EmployeeService真实对象而不是代理对象。
解决办法:
方法1:
在方法A上开启事务,方法B不用事务或默认事务,
并在方法A的catch中throw new RuntimeException();
(在没指定rollbackFor时,默认回滚的异常为RuntimeException),这样使用的就是方法A的事务。(一定要throw new RuntimeException();否则异常被捕捉处理,同样不会回滚。)
如下:
@Transactional() //开启事务
public void save(){try { this.saveEmployee(); }catch (Exception e){e.printStackTrace();throw new RuntimeException();}
}
方法2:
方法2、方法A上可以不开启事务,方法B上开启事务,并在方法A中将this调用改成动态代理调用(AopContext.currentProxy()),如下:
public void save(){try { EmployeeService proxy =(EmployeeService) AopContext.currentProxy();proxy.saveEmployee();}catch (Exception e){e.printStackTrace();}
}
另外还需要注意: 使用动态代理时候记得,在启动类配置开启代理
需要在启动类配置开启代理配置上:
@EnableTransactionManagement
@EnableAspectJAutoProxy(exposeProxy = true)
@EnableTransactionManagement
@SpringBootApplication
@EnableFeignClients(basePackages={"com.***"})
@EnableEurekaClient
@MapperScan("com.***.production.order.dao.mapper")
@ComponentScan(basePackages={"com.***"})
// 暴露代理
@EnableAspectJAutoProxy(exposeProxy = true)
public class ProductionOrderJobApplication {protected final static Logger logger = LoggerFactory.getLogger( ProductionOrderJobApplication.class);public static void main(String[] args) {SpringApplication app = new SpringApplication( ProductionOrderJobApplication.class);app.setBannerMode(Banner.Mode.OFF);app.run(args);logger.info("ProductionOrderJobApplication is success!");}@Beanpublic RequestContextListener requestContextListener(){return new RequestContextListener();}}
补充一点: 拆类 的方法可以试试
最终解决方案: 拆类的方法
Spring事务失效 -方法内部调用相关推荐
- Spring事务总结(一) 内部调用事务失效、异常回滚
Spring事务总结(一) 内部调用事务失效.异常回滚 参考文章: (1)Spring事务总结(一) 内部调用事务失效.异常回滚 (2)https://www.cnblogs.com/gss128/p ...
- Spring事务内方法调用自身事务
Spring事务内方法调用自身事务 增强的三种方式 ServiceA.java文件: 查看Spring Tx的相关日志: 可以看到只创建了一个事物ServiceA.service方法的事务,但是cal ...
- 聊聊Spring事务失效的12种场景,太坑人了
前言 对于从事java开发工作的同学来说,spring的事务肯定再熟悉不过了. 在某些业务场景下,如果一个请求中,需要同时写入多张表的数据.为了保证操作的原子性(要么同时成功,要么同时失败),避免数据 ...
- 每日一博 - 常见的Spring事务失效事务不回滚案例集锦
文章目录 事务不生效 方法内部调用 修复方法一 : [新加一个Service方法] 修复方法二:[在该Service类中注入自己] 修复方法三:[通过AopContent类]<---- 推荐 访 ...
- 详细整理Spring事务失效的具体场景及解决方案
实际项目开发中,如果涉及到多张表操作时,为了保证业务数据的一致性,大家一般都会采用事务机制:好多小伙伴可能只是简单了解一下,遇到事务失效的情况,便会无从下手,溪源此篇文章给大家整理了一下常见Sprin ...
- 面试官:Spring事务失效的场景有哪些?如何解决?
作者:溪~源 blog.csdn.net/xuan_lu/article/details/107797505 实际项目开发中,如果涉及到多张表操作时,为了保证业务数据的一致性,大家一般都会采用事务机 ...
- 你否有遇到Spring事务失效,花费太多时间找bug
作者:溪~源 来源:blog.csdn.net/xuan_lu/article/details/107797505 实际项目开发中,如果涉及到多张表操作时,为了保证业务数据的一致性,大家一般都会采用事 ...
- spring事务失效了? @Transactional不管用了 ?看看这些@Transation的坑
spring事务失效了? @Transactional不管用了 ?看看这些@Transactional的坑 文章目录 spring事务失效了? @Transactional不管用了 ?看看这些@Tra ...
- 详解spring事务失效和回滚失败的场景
详解spring事务失效和回滚失败的场景 详解spring事务失效和回滚失败的场景 前言 一 .事务不生效 1.访问权限问题 2. 方法用final修饰 3.方法的内部调用 3.1 新加一个Servi ...
最新文章
- 4-2-串的堆存储结构-串-第4章-《数据结构》课本源码-严蔚敏吴伟民版
- java选择哪款eclipse_写java程序用哪一个版的eclipse比较好
- jvm二:类加载,连接,初始化
- zk ui_高级ZK:异步UI更新和后台处理–第1部分
- html十css十javascript,html代码,css代码,JavaScript代码, | 重蔚自留地
- Fedora升级后Python虚拟环境中的pip报错
- redhat简单安装Samba,JDK环境,Tomcat,Oracle11G
- makefile obj文件路径_makefile中包含的文件的路径
- 深度技术 GHOSTXPSP3 快速装机 2013圣诞节专版
- android lame,Android 采用Lame编码器编码mp3文件
- 如何制定项目里程碑?
- PC 上安装Windows10系统到硬盘上ESP分区丢失,新建ESP分区修复引导ESP分区创建失败解决办法
- Servlet/Filter中的url-pattern
- 进击的“懒人经济”,快手又迎来一个万亿蓝海市场
- 【读 深入浅出数据分析】 一日一章 读书第三天 第三章-最优化:寻找最大值
- 1.学生党如何查找文献书籍
- 记一次git pull 错误
- 欧几里得变换(Euclidean transformation)详解
- 语法基础(三. 类,属性,方法,方法重载,方法重写,构造方法,访问修饰符)
- 去掉/隐藏 word的回车符
热门文章
- Spark GraphX算法 - Aggregate Messages (aggregateMessages)算法
- Idea 版本控制冲突解决
- css 商城 两列_css大法之使用伪元素实现超实用的图标库(附源码
- JavaScript(五)——错误处理
- 牛客练习赛50-C——tokitsukaze and Soldier
- linux mysql root用户密码_Linux下修改Mysql的用户(root)的密码
- Statement returned more than one row, where no more than one was expected
- Dubbo与Spring Cloud
- P2574 XOR的艺术
- solr索引创建流程