@Transactional注解失效的解决方案
一、前言
开发中我们经常使用 @Transactional注解来启用Spring事务管理,但是如果使用方法不当,会遇到注解不生效该事务回滚的地方却没有回滚的问题。
总结下一般是以下几个原因:
- @Transactional 注解只能应用到 public 可见度的方法上。 如果应用在protected、private或者 package可见度的方法上,也不会报错,不过事务设置不会起作用。
- 默认情况下,spring会对unchecked异常进行事务回滚;如果是checked异常则不回滚。针对这种情况,可以try catch checked异常后进行手动事务回滚。
- 数据库引擎要支持事务,如果是mysql,注意表要使用支持事务的引擎,比如InnoDB,如果是MyISAM,事务是不起作用的。
- 同一个类中, 一个no-transactional的方法去调用transactional的方法, 事务会失效。
本文主要讲第四种情况如何处理。
二、示例
执行add() 方法后数据库插入了两条数据,也就说明以上两段代码中,doAdd()方法的事务增强都不会执行,具体原因可以参考这篇文章。
那么如果想让doAdd()方法在发生异常时数据库事务回滚,有什么解决办法吗?
第一步开启配置expose-proxy
如果使用的xml配置文件的方式,则添加如下内容:
<aop:aspectj-autoproxy expose-proxy="true" />
如果用的SpringBoot框架,则直接在启动类上添加如下注解即可。
@EnableAspectJAutoProxy(proxyTargetClass = true,exposeProxy = true)
第二步修改代码
将原来的调用代码this.doAdd(person); 改为 ((PersonService)AopContext.currentProxy()).doAdd(person);
再进行测试发现数据库只插入了一条数据(person2),说明doAdd() 方法里的事务增强生效了。
三、源码分析
点进 @EnableAspectJAutoProxy 注解代码如下:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
boolean proxyTargetClass() default false;
boolean exposeProxy() default false;
}
发现它注入了一个Bean AspectJAutoProxyRegistrar,再看看这个AspectJAutoProxyRegistrar是什么。
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
// 解析注解EnableAspectJAutoProxy
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
// 如果设置了exposeProxy=true就强制使用
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
}
AopConfigUtils#forceAutoProxyCreatorToExposeProxy
// 强制使用的过程其实也是一个属性设置的过程
public static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) {
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
definition.getPropertyValues().add("exposeProxy", Boolean.TRUE);
}
}
/**
* The bean name of the internally managed auto-proxy creator.
*/
public static final String AUTO_PROXY_CREATOR_BEAN_NAME =
"org.springframework.aop.config.internalAutoProxyCreator";
@Transactional注解失效的解决方案的更多相关文章
- @Transactional 注解失效场景
@Transactional可以用在接口.类.类方法上. 作用于类:当把@Transactional注解放在类上时,表示该类的所有public方法都配置了该事物注解. 作用于方法:表示该方法配置了事物 ...
- @Transactional注解失效
一.特性 先来了解一下@Transactional注解事务的特性吧,可以更好排查问题 1.service类标签(一般不建议在接口上)上添加@Transactional,可以将整个类纳入spring事务 ...
- 一口气说出 6种,@Transactional注解的失效场景
整理了一些Java方面的架构.面试资料(微服务.集群.分布式.中间件等),有需要的小伙伴可以关注公众号[程序员内点事],无套路自行领取 一口气说出 9种 分布式ID生成方式,面试官有点懵了 面试总被问 ...
- @Transactional注解的失效场景
一口气说出 6种,@Transactional注解的失效场景 计算机java编程 发布时间: 20-03-1912:35优质科技领域创作者 引言 昨天公众号粉丝咨询了一个问题,说自己之前面试被问@Tr ...
- spring事务注解失效问题
问题描述: 由于工作需要,需要在spring中配置两个数据源,有一天突然发现@Transactional注解失效 环境框架: springmvc+spring+spring jdbcTemplate ...
- Spring aop注解失效
问题 在spring 中使用 @Transactional . @Cacheable 或 自定义 AOP 注解时,对象内部方法中调用该对象的其他使用aop机制的方法会失效. @Transactiona ...
- Spring @Transactional注解不起作用解决办法及原理分析
Transactional失效场景介绍 第一种 Transactional注解标注方法修饰符为非public时,@Transactional注解将会不起作用.例如以下代码. 定义一个错误的@Trans ...
- Spring中@Translational注解失效场景
今天面试被问到@Translational注解什么场景下失效,我一脸懵逼,说的恍恍惚惚的,下来我就总结一下@Translational注解失效的场景! @Transactional 注解相信大家并不陌 ...
- @Transaction注解失效的几种场景
一.@Transactional介绍 1.@Transactional注解可以作用于哪些地方? @Transactional 可以作用在接口.类.类方法上. 作用于类:表示所有该类的public方法都 ...
随机推荐
- java并发编程实战《二十一》无锁工具类
不安全的累加代码,如下 1 public class Test { 2 long count = 0; 3 void add10K() { 4 int idx = 0; 5 while(idx++ & ...
- 通过Apache Hudi和Alluxio建设高性能数据湖
T3出行的杨华和张永旭描述了他们数据湖架构的发展.该架构使用了众多开源技术,包括Apache Hudi和Alluxio.在本文中,您将看到我们如何使用Hudi和Alluxio将数据摄取时间缩短一半.此 ...
- Python音视频开发:消除抖音短视频Logo和去电视台标的实现详解
☞ ░ 前往老猿Python博文目录 ░ 一.引言 对于带Logo(如抖音Logo.电视台标)的视频,有三种方案进行Logo消除: 直接将对应区域用对应图像替换: 直接将对应区域模糊化: 通过变换将要 ...
- Python的富比较方法__lt__、__gt__之间的关联关系分析
Python的富比较方法包括__lt__.__gt__分别表示:小于.大于,对应的操作运算符为:"<".">".那么是否象普通数字运算一样,这两个方 ...
- PyQt(Python+Qt)学习随笔:QTableWidgetItem项的复选状态checkState访问方法
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 QTableWidget表格部件中的QTableWidgetItem项可以单独设置复选状态,如图所有 ...
- 第6章 Python中的动态可执行方法目录
第6.1节 Python代码编译 第6.2节 Python特色的动态可执行方法简介 第6.3节 Python动态执行之动态编译的compile函数 第6.4节 Python动态表达式计算:eval函数 ...
- 第11.3节 Python正则表达式搜索支持函数search、match、fullmatch、findall、finditer
一. 概述 re模块的函数search.match.fullmatch.findall.finditer都是用于搜索文本中是否包含指定模式的串,函数的参数都是一样的,第一个参数是模式串.第二个是搜索文 ...
- PyQt(Python+Qt)学习随笔:Mode/View中的枚举类 QItemSelectionModel.SelectionFlag取值及含义
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 以上取值可以通过或操作进行组合使用. 老猿Python,跟老猿学Python! 老猿Python博文 ...
- 孪生网络入门(下) Siamese Net分类服装MNIST数据集(pytorch)
主题列表:juejin, github, smartblue, cyanosis, channing-cyan, fancy, hydrogen, condensed-night-purple, gr ...
- Centos 7 下的java安装
安装java 下载jdk的安装包,放到 /usr/local 目录下 创建一个 java 的目录存放 jdk 1 mkdir java 解压java安装包 1 tar -zxvf "jdk名 ...