当前位置:网站首页>如何将 @Transactional 事务注解运用到炉火纯青?
如何将 @Transactional 事务注解运用到炉火纯青?
2022-07-07 10:34:00 【Java精选】
前两天在工作中忙的焦头烂额,涉及到@Transactional
对于事务的控制,便仔细研究了一下,颇有所获,花费好了几天测试整理,今天才发表出来,希望看到博客的老铁们能有所获吧。话不多说直奔正题。
所谓事务的传播行为是指,如果在开始当前事务之前,一个事务上下文已经存在,此时有若干选项可以指定一个事务性方法的执行行为。在TransactionDefinition
定义中包括了如下几个表示传播行为的常量:
TransactionDefinition.PROPAGATION_REQUIRED
:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。这是默认值。TransactionDefinition.PROPAGATION_REQUIRES_NEW
:创建一个新的事务,如果当前存在事务,则把当前事务挂起。TransactionDefinition.PROPAGATION_SUPPORTS
:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。TransactionDefinition.PROPAGATION_NOT_SUPPORTED
:以非事务方式运行,如果当前存在事务,则把当前事务挂起。TransactionDefinition.PROPAGATION_NEVER
:以非事务方式运行,如果当前存在事务,则抛出异常。TransactionDefinition.PROPAGATION_MANDATORY
:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。TransactionDefinition.PROPAGATION_NESTED
:如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED
。
然后说一下Spring事务的回滚机制
Spring的AOP即声明式事务管理默认是针对unchecked exception
回滚。Spring的事务边界是在调用业务方法之前开始的,业务方法执行完毕之后来执行commit or rollback
(Spring默认取决于是否抛出runtimeException
)。
如果你在方法中有try{}catch(Exception e){}
处理,那么try里面的代码块就脱离了事务的管理,若要事务生效需要在catch中throw new RuntimeException ("xxxxxx");
这一点也是面试中会问到的事务失效的场景。
再简单介绍一下@Transactional
注解底层实现方式吧,毫无疑问,是通过动态代理,那么动态代理又分为JDK自身和CGLIB,这个也不多赘述了,毕竟今天的主题是如何将@Transactional
对于事物的控制应用到炉火纯青。哈哈~
第一点要注意的就是在@Transactional
注解的方法中,再调用本类中的其他方法method2时,那么method2方法上的@Transactional
注解是不!会!生!效!的!但是加上也并不会报错,拿图片简单帮助理解一下吧。这一点也是面试中会问到的事务失效的场景。
通过代理对象在目标对象前后进行方法增强,也就是事务的开启提交和回滚。那么继续调用本类中其他方法是怎样呢,如下图:
可见目标对象内部的自我调用,也就是通过this.指向的目标对象将不会执行方法的增强。
先说第二点需要注意的地方,等下说如何解决上面第一点的问题。第二点就是@Transactional
注解的方法必须是公共方法,就是必须是public修饰符!!!另外,公众 号Java精选,回复java面试,获取面试资料。
至于这个的原因,发表下个人的理解吧,因为JVM的动态代理是基于接口实现的,通过代理类将目标方法进行增强,想一下也是啦,没有权限访问那么你让我怎么进行,,,好吧,这个我也没有深入研究底层,个人理解个人理解。
在这里我也放个问题吧,希望有高手可以回复指点指点我,因为JVM动态代理是基于接口实现的,那么是不是service层都要按照接口和实现类的开发模式,注解才会生效呢,就是说controller
层直接调用没有接口的service层,加了注解也一样不起作用吧,这个懒了,没有测试,其一是因为没有人会这么开发吧,其二是我就认为是不起作用的,哈哈
下面来解决一下第一点的问题,如何在方法中调用本类中其他方法呢。
通过AopContext.currentProxy ()
获取到本类的代理对象,再去调用就好啦。因为这个是CGLIB实现,所以要开启AOP,当然也很简单,在springboot启动类上加上注解@EnableAspectJAutoProxy(exposeProxy = true)
就可以啦,这个依赖大家自行搜一下就好啦。要注意,注意,代理对象调用的方法也要是public修饰符,否则方法中获取不到注入的bean,会报空指针错误。
emmmm,我先把调用的方式和结果说下吧。自己简单写了代码,有点粗糙,就不要介意啦,嘿嘿。。。
Controller中调用Service
@RestController
public class TransactionalController {
@Autowired
private TransactionalService transactionalService;
@PostMapping("transactionalTest")
public void transacionalTest(){
transactionalService.transactionalMethod();
}
}
Service中实现对事务的控制:接口
public interface TransactionalService {
void transactionalMethod();
}
Service中实现对事务的控制:实现类(各种情况的说明都写在图片里了,这样方便阅读,有助于快速理解吧)
上面两种情况不管使不使用代理调用方法1和方法2,方法transactionalMethod
都处在一个事务中,四条更新操作全部失败。
那么有人可能会有疑问了,在方法1和方法2上都加@Transactional
注解呢?答案是结果和上面是一致的。
小结只要方法transactionalMethod
上有注解,并且方法1和方法2都处于当前事务中(不使用代理调用,方法1和方法2上的@Transactional
注解是不生效的;使用代理,需要方法1和方法2都处在transactionalMethod
方法的事务中,默认或者嵌套事务均可,当然也可以不加@Transactional
注解),那么整体保持事务一致性。
如果想要方法1和方法2均单独保持事务一致性怎么办呢,刚说过了,如果不是用代理调用@Transactional
注解是不生效的,所以一定要使用代理调用实现,然后让方法1和方法2分别单独开启新的事务,便OK啦。下面摆上图片。
这两种情况都是方法1和方法2均处在单独的事务中,各自保持事务的一致性。
接下来进行进一步的优化,可以在transactionalMethod
方法中分别对方法1和方法2进行控制。要将代码的艺术发挥到极致嘛,下面装逼开始。
代码太长了,超过屏幕了,粘贴出来截的图,红框注释需要仔细看,希望不要影响你的阅读体验,至此,本篇关于@Transactioinal
注解的使用就到此为止啦,
简单总结一下吧:
1、就是@Transactional
注解保证的是每个方法处在一个事务,如果有try一定在catch中抛出运行时异常。
2、方法必须是public修饰符。否则注解不会生效,但是加了注解也没啥毛病,不会报错,只是没卵用而已。
3、this.本方法的调用,被调用方法上注解是不生效的,因为无法再次进行切面增强。
如果有更细致的讨论欢迎评论,感谢阅读。
作者:范学博
https://blog.csdn.net/fanxb92/article/details/81296005
公众号“Java精选”所发表内容注明来源的,版权归原出处所有(无法查证版权的或者未注明出处的均来自网络,系转载,转载的目的在于传递更多信息,版权属于原作者。如有侵权,请联系,笔者会第一时间删除处理!
最近有很多人问,有没有读者交流群!加入方式很简单,公众号Java精选,回复“加群”,即可入群!
Java精选面试题(微信小程序):3000+道面试题,包含Java基础、并发、JVM、线程、MQ系列、Redis、Spring系列、Elasticsearch、Docker、K8s、Flink、Spark、架构设计等,在线随时刷题!
------ 特别推荐 ------
特别推荐:专注分享最前沿的技术与资讯,为弯道超车做好准备及各种开源项目与高效率软件的公众号,「大咖笔记」,专注挖掘好东西,非常值得大家关注。点击下方公众号卡片关注。
文章有帮助的话,点在看,转发吧!
边栏推荐
- 对话PPIO联合创始人王闻宇:整合边缘算力资源,开拓更多音视频服务场景
- 【统计学习方法】学习笔记——支持向量机(上)
- leetcode刷题:二叉树27(删除二叉搜索树中的节点)
- Decrypt gd32 MCU product family, how to choose the development board?
- JS to convert array to tree data
- Is it safe to open an account in Ping An Securities mobile bank?
- How to use PS link layer and shortcut keys, and how to do PS layer link
- SQL injection -- Audit of PHP source code (take SQL lab 1~15 as an example) (super detailed)
- VSCode的学习使用
- Static comprehensive experiment
猜你喜欢
Airserver automatically receives multi screen projection or cross device projection
idm服务器响应显示您没有权限下载解决教程
The IDM server response shows that you do not have permission to download the solution tutorial
Routing strategy of multi-point republication [Huawei]
普乐蛙小型5d电影设备|5d电影动感电影体验馆|VR景区影院设备
2022危险化学品生产单位安全生产管理人员考题及在线模拟考试
【统计学习方法】学习笔记——支持向量机(上)
【PyTorch实战】图像描述——让神经网络看图讲故事
leetcode刷题:二叉树19(合并二叉树)
[deep learning] image multi label classification task, Baidu paddleclas
随机推荐
When OSPF specifies that the connection type is P2P, it enables devices on both ends that are not in the same subnet to Ping each other
Idea 2021 Chinese garbled code
Epp+dis learning path (1) -- Hello world!
【从 0 开始学微服务】【03】初探微服务架构
How to use PS link layer and shortcut keys, and how to do PS layer link
Attack and defense world - PWN learning notes
数据库安全的重要性
OSPF exercise Report
Charles: four ways to modify the input parameters or return results of the interface
How much does it cost to develop a small program mall?
leetcode刷题:二叉树25(二叉搜索树的最近公共祖先)
Vxlan 静态集中网关
NGUI-UILabel
[statistical learning method] learning notes - support vector machine (I)
SQL injection -- Audit of PHP source code (take SQL lab 1~15 as an example) (super detailed)
NGUI-UILabel
NPM instal reports agent or network problems
数据库系统原理与应用教程(008)—— 数据库相关概念练习题
An error occurred when vscade tried to create a file in the target directory: access denied [resolved]
(待会删)yyds,付费搞来的学术资源,请低调使用!