@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方法都 ...
随机推荐
- 老猿学5G:融合计费基于流计费的触发器Triggers
☞ ░ 前往老猿Python博文目录 ░ 一.概述 每个触发条件都是一个可计费事件.SMF中的功能体CTF在用户上网时达到一定条件就会向CHF上报流量,而CTF什么时候触发流量上报是由CTF中的触发器 ...
- 第11.19节 Python 中正则表达式的扩展功能:前视断言和前视取反
一. 引言 在<第11.16节 Python正则元字符"()"(小括号)与组(group)匹配模式>中老猿介绍了组匹配模式的命名组功能及引用组功能,这两者都是组模式的扩 ...
- XSS挑战赛(3)
查看关键代码: <?php ini_set("display_errors", 0); $str = $_GET["keyword"]; $str00 = ...
- 题解-CF1282E The Cake Is a Lie
题面 CF1282E The Cake Is a Lie \(T\) 组测试数据.每次给一个 \(n\) 边形的三角剖分,求节点顺序和剖分顺序. 数据范围:\(3\le n\le 10^5\),\(\ ...
- 学习笔记:斜率优化DP
作为数学渣,先复习一下已知两点\((x_1, y_1)\), \((x_2, y_2)\),怎么求过两点的一次函数的斜率... 待定系数法代入 \(y = kx + b\) 有: \(x_1k + b ...
- 题解-[国家集训队]Crash的数字表格 / JZPTAB
题解-[国家集训队]Crash的数字表格 / JZPTAB 前置知识: 莫比乌斯反演 </> [国家集训队]Crash的数字表格 / JZPTAB 单组测试数据,给定 \(n,m\) ,求 ...
- java.lang.UnsupportedOperationException: Unable to create instance of org.fisco.bcos.web3j.abi.datatypes.generated.Int256
Contract Address : 0x967f92adc229b77dda64b42af21ea1ff1b0702eb Unable to create instance of org.fisco ...
- Pytest学习(20)- allure之@allure.step()、allure.attach的详细使用
一.@allure.step的用法 可以理解为我们编写测试用例中的每一步操作步骤,而在allure中表示对每个测试用例进行非常详细的步骤说明 通过 @allure.step(),可以让测试用例在all ...
- DVWA各等级sql注入
sql全等级注入 level:low <?php if( isset( $_REQUEST[ 'Submit' ] ) ) { //判断submit是否存在 // Get input $id = ...
- Pytest 学习(二十七)- Jenkins+Allure+Pytest的持续集成
一.配置 allure 环境变量 1.下载 allure是一个命令行工具,可以去 github 下载最新版:https://github.com/allure-framework/allure2/re ...