Spring事务不生效问题
事务未生效可能造成严重的数据不一致性问题,因而保证事务生效至关重要。Spring事务是通过Spring aop实现的,所以不生效的本质问题是spring aop没生效,或者说没有代理成功,所以有必要了解下spring aop。
spring事务不生效场景
- 非public修饰方法
- private修饰
@Transactional
private void save(){...}
调用save方法,事务不生效 - protected修饰
@Transactional
protected void save(){...}
调用save方法,事务不生效
- private修饰
- final修饰的public法或类
- final修饰方法
@Transactional
public final void save(){...}
调用save方法,事务不生效 - final修饰类
@Transactional
public final class UserService{...}
调用UserService的方法,事务不生效
- final修饰方法
- 被代理对象内部方法调用
- 非事务方法调用内部事务方法
public void save(){
insert()
}
@Transactional
public void insert(){...}
此时调用save()方法,insert()上的事务不生效 - 事务方法调用内部事务方法
@Transactional
public void save(){
insert()
}
@Transactional
public void insert(){...}
此时调用save()方法,insert()上的事务不生效,save()方法正常调用时(非内部方法调用)事务生效
- 非事务方法调用内部事务方法
Spring aop的简单介绍
spring aop支持动态代理(运行时代理)和静态代理(编译期织入)
基本概念
- target对象
目标对象,即想要代理的目标。 - proxy
代理对象,访问目标对象的方法,需要通过代理对象,无法直接访问目标对象。
代理对象可能允许,最终调用目标对象方法,也可能不允许。
- target对象
静态代理(Aspectj)
1.该实现需要使用特殊编译器,一般不使用,spring只是提供相应的整合实现。
2.使用动态代理已经可以完成80%以上的需求了。
3.本文也是基于动态代理的情况下讨论事务不生效情况的。
4.因此在此不展开详细讨论。动态代理(CGLIB&JDK)
- JDK动态代理
1.JDK动态代理通过实现相同接口实现代理(Proxy)
2.spring管理的Bean中是对应的是Proxy
3.Proxy对象中包含target对象
4.目标方法可以执行时,总是调用target的原生方法
5.事务aop默认publicMethodsOnly(该配置未提供直接修改-AnnotationTransactionAttributeSource) - CGLIB动态代理
1.CGLIB动态代理通过继承目标类生成子类作为代理
2.spring管理的Bean中是对应的是Proxy
3.Proxy对象中包含target对象
4.目标方法可以执行时,总是调用target的原生方法
5.事务aop默认publicMethodsOnly(该配置未提供直接修改-AnnotationTransactionAttributeSource)
- JDK动态代理
Spring 事务不生效情况(即aop不生效情况),原因解析
- 无法代理
- 方法使用非public修饰(protected、private等等)
@Transactional
private void save(){...}
或
@Transactional
protected void save(){...}
spring 事务aop默认publicMethodsOnly,即只有public修饰的方法,会被代理,private和protected修饰的方法save()无法被代理,事务无效。 - 方法使用final修饰
@Transactional
public final void save(){...}
CGLIB动态代理通过生成子类的方式代理,final方法无法重写 - 类使用final修饰
@Transactional
public final class UserService{...}
CGLIB动态代理通过生成子类的方式代理,final类无法生成子类
- 方法使用非public修饰(protected、private等等)
- 未通过proxy对象调用
- 非事务方法调用内部事务方法
public void save(){
insert()
}
@Transactional
public void insert(){...}
该情况隐含使用this关键字,因此被代理对象的内部事务方法insert()直接被调用,而不经过代理对象;
内部方法insert()上的事务无效。 - 事务方法调用内部事务方法
@Transactional
public void save(){
insert()
}
@Transactional
public void insert(){...}
该情况隐含使用this关键字,因此被代理对象的内部事务方法insert()直接被调用,而不经过代理对象;
内部方法insert()上的事务无效,但是事务方法save()正确调用时(通过代理对象调用),save()方法的事务生效。
- 非事务方法调用内部事务方法
调试辅助
当无法通过代码分析确定是否有事务(aop是否代理成功)时,可以在开发环境调试确认
- 事务AOP
在配置了expose-proxy=true时,调用静态方法TransactionAspectSupport.currentTransactionStatus()可以获取当前事务信息;
该信息存储在ThreadLocal类型的线程变量;不存在时会抛异常,所以使用时需要try-catch。 - 其他AOP
在配置了expose-proxy=true时,调用静态方法AopContext.currentProxy()可以获取当前代理对象;该对象存储在ThreadLocal类型的线程变量;不存在时会抛异常,所以使用时需要try-catch。
Spring事务不生效问题的更多相关文章
- Spring基础系列-Spring事务不生效的问题与循环依赖问题
原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/9476550.html 一.提出问题 不知道你是否遇到过这样的情况,在ssm框架中开发we ...
- mysql测试spring事务是否生效
同时对三张表进行插入操作,事务保证完整性.下面进行简单测试: 1. 锁定表 锁定用户表 LOCK TABLES user WRITE; 查看表是否锁定: show ; 显示被锁定的表. 2. 验证在同 ...
- [转]Spring事务嵌套引发的血案---Transaction rolled back because it has been marked as rollback-only
原文地址:https://blog.csdn.net/f641385712/article/details/80445912 1.概述 想必大家一想到事务,就想到ACID,或者也会想到CAP.但笔者今 ...
- spring中注解式事务不生效的问题
常用的解决方法可以百度,我针对我的问题描述一下 Mysql中InnoDB引擎才支持事务, MyISAM不支持事务. 当你尝试了各种方法解决spring中注解式事务不生效时, 一定要查看一下数据库中表的 ...
- 分析spring事务@Transactional注解在同一个类中的方法之间调用不生效的原因及解决方案
问题: 在Spring管理的项目中,方法A使用了Transactional注解,试图实现事务性.但当同一个class中的方法B调用方法A时,会发现方法A中的异常不再导致回滚,也即事务失效了. 当这个方 ...
- Spring中同一个service中方法相互调用事务不生效问题解决方案
问题描述: 我们在用Spring框架开发Web项目过程中,经常需要用同一个service中的一个方法调用另一个方法,如果此时调用方没有添加事务注解@Transactional,而在被调用方添加事务注解 ...
- 两个与spring事务相关的问题
有些spring相关的知识点之前一直没有仔细研究:比如spring的事务,并不是没有使用,也曾经简单的在某些需要事务处理的方法上通过增加事务注解来实现事务功能,仅仅是跟随使用(甚至并未测试过事务的正确 ...
- 【转】Spring事务管理
原文链接 在 Spring 中,事务是通过 TransactionDefinition 接口来定义的.该接口包含与事务属性有关的方法.具体如清单 1 所示: 清单 1. TransactionDefi ...
- Spring事务讲解示例
Spring 事务Transaction1.事务的属性1.1 事务隔离IsolationLevel1.2 事务传播PropagationBehavior1.3 事务超时Timeout1.4 只读状态R ...
随机推荐
- 怎样在Linux中查看apache是用那个httpd.conf
第一步:找到apache启动命令: [root@WAPBJ01 ~]# ps -ef|grep httpdroot 10575 1 0 19:45 ? 00:00:03 ...
- js判断访客来源网址和关键字
加入现在有A.B两个站,A为友站,B为我站. 希望判断使用从A站连来时,就把访问者拒绝在门外,只要用简单几行的javascript,就可抓到使用的来源,以及作出一些防范的措施. <script ...
- Selenium多浏览器并行测试
如果需要同时在IE.firefox.chrome进行测试,可以使用grid. Selenium Grid是一个智能代理服务器,允许Selenium测试将命令路由到远程Web浏览器实例.其目的是提供一种 ...
- python学习笔记(十六)-Python多线程多进程
一.线程&进程 对于操作系统来说,一个任务就是一个进程(Process),比如打开一个浏览器就是启动一个浏览器进程,打开一个记事本就启动了一个记事本进程,打开两个记事本就启动了两个记事本进程, ...
- ci框架 自定义配置方法
系统自动在Application文件夹下生成的config.php文件,采用key-value关联数组的形式来存放配置项和值.为了使结构更清晰,手动新建另外一个配置文件myconfig.php,所采用 ...
- ES增删改查
了解了一下python对es 7.5的操作,记录下,不难: #!/usr/bin/env python # -*- coding: UTF-8 -*- from settings import Con ...
- Jemter请求乱码解决方案
1:jemeter查看结果树乱码 (1)在jmeter的bin目录下找到jmeter.properties这个文件,添加上 sampleresult.default.encoding=utf-8 (2 ...
- 华为云计算IE面试笔记-华为云计算解决方案业务迁移支持哪些迁移?有哪些特点?请描述基本的业务交付流程、业务迁移流程和原则。
1. 迁移场景:华为云计算解决方案按照源端环境来说,支持P2V.V2V(P2V:物理设备(操作系统及其上的应用软件和数据)迁移到华为虚拟化平台.V2V:其他厂商的虚拟化平台迁移到华为虚拟化平台.)以及 ...
- spring boot处理跨域请求代码
@Configuration @WebFilter(filterName = "CorsFilte") public class CorsFilter implements Fil ...
- The Data Way Vol.4|开源是创造软件诸多方法中最好的一种形式
关于「The Data Way」 「The Data Way」是由 SphereEx 公司出品的一档播客节目.这里有开源.数据.技术的故事,同时我们关注开发者的工作日常,也讨论开发者的生活日常:我们聚 ...