Spring 事务失效的 8 大场景,面试官直呼666...

前几天发了一篇文章里面有一个关于事务失效的问题:

用 Spring 的 @Transactional 注解控制事务有哪些不生效的场景?

其中有个热心粉丝留言分享了下,我觉得总结得有点经验,给置顶了:

但是我觉得还是总结得不够全,今天栈长我再总结一下,再延着这位粉丝的总结再补充完善一下,不用说,我肯定也不见得总结全,但希望可以帮忙有需要的人。

1 数据库引擎不支持事务

这里以 MySQL 为例,其 MyISAM 引擎是不支持事务操作的,InnoDB 才是支持事务的引擎,一般要支持事务都会使用 InnoDB。

根据 MySQL 的官方文档:

https://dev.mysql.com/doc/refman/5.5/en/storage-engine-setting.html

从 MySQL 5.5.5 开始的默认存储引擎是:InnoDB,之前默认的都是:MyISAM,所以这点要值得注意,底层引擎不支持事务再怎么搞都是白搭。

2 没有被 Spring 管理

如下面例子所示:

// @Service
public class OrderServiceImpl implements OrderService {@Transactionalpublic void updateOrder(Order order) {// update order}}

如果此时把 @Service 注解注释掉,这个类就不会被加载成一个 Bean,那这个类就不会被 Spring 管理了,事务自然就失效了。

3 方法不是 public 的

以下来自 Spring 官方文档:

When using proxies, you should apply the @Transactional annotation only to methods with public visibility. If you do annotate protected, private or package-visible methods with the @Transactional annotation, no error is raised, but the annotated method does not exhibit the configured transactional settings. Consider the use of AspectJ (see below) if you need to annotate non-public methods.

大概意思就是 @Transactional 只能用于 public 的方法上,否则事务不会失效,如果要用在非 public 方法上,可以开启 AspectJ 代理模式。

4 自身调用问题

来看两个示例:

@Service
public class OrderServiceImpl implements OrderService {public void update(Order order) {updateOrder(order);}@Transactionalpublic void updateOrder(Order order) {// update order}}

update方法上面没有加 @Transactional 注解,调用有 @Transactional 注解的 updateOrder 方法,updateOrder 方法上的事务管用吗?

再来看下面这个例子:

@Service
public class OrderServiceImpl implements OrderService {@Transactionalpublic void update(Order order) {updateOrder(order);}@Transactional(propagation = Propagation.REQUIRES_NEW)public void updateOrder(Order order) {// update order}}

这次在 update 方法上加了 @Transactional,updateOrder 加了 REQUIRES_NEW 新开启一个事务,那么新开的事务管用么?

这两个例子的答案是:不管用!

因为它们发生了自身调用,就调该类自己的方法,而没有经过 Spring 的代理类,默认只有在外部调用事务才会生效,这也是老生常谈的经典问题了。

这个的解决方案之一就是在的类中注入自己,用注入的对象再调用另外一个方法,这个不太优雅,另外一个可行的方案可以参考《Spring 如何在一个事务中开启另一个事务?》这篇文章。

5 数据源没有配置事务管理器

@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {return new DataSourceTransactionManager(dataSource);
}

如上面所示,当前数据源若没有配置事务管理器,那也是白搭!

6 不支持事务

来看下面这个例子:

@Service
public class OrderServiceImpl implements OrderService {@Transactionalpublic void update(Order order) {updateOrder(order);}@Transactional(propagation = Propagation.NOT_SUPPORTED)public void updateOrder(Order order) {// update order}}

Propagation.NOT_SUPPORTED: 表示不以事务运行,当前若存在事务则挂起。

这表示不支持以事务的方式运行,所以即使事务生效也是白搭!

7 异常被吃了

这个也是出现比较多的场景:

// @Service
public class OrderServiceImpl implements OrderService {@Transactionalpublic void updateOrder(Order order) {try {// update order} catch {}}}

把异常吃了,然后又不抛出来,事务也不会回滚!

8 异常类型错误

上面的例子再抛出一个异常:

// @Service
public class OrderServiceImpl implements OrderService {@Transactionalpublic void updateOrder(Order order) {try {// update order} catch {throw new Exception("更新错误");}}}

这样事务也是不生效的,因为默认回滚的是:RuntimeException,如果你想触发其他异常的回滚,需要在注解上配置一下,如:

@Transactional(rollbackFor = Exception.class)

这个配置仅限于 Throwable 异常类及其子类。

总结

本文总结了 8 种事务失效的场景,其实发生最多就是自身调用、异常被吃、异常抛出类型不对这 3 个了,像文章开头说的那样,本文不一定总结得全,只是总结常见的事务失效的场景,如果你还知道其他场景也欢迎留言分享。


往期推荐

千万不要这样写代码!9种常见的OOM场景演示


Spring Boot集成Redis,这个坑把我害惨了!


SpringBoot接口幂等性实现的4种方案!


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/544964.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python 示例_Python条件类| release()方法与示例

python 示例Python Condition.release()方法 (Python Condition.release() Method) release() is an inbuilt method of the Condition class of the threading module in Python. release()是Python中线程模块的Condition类的内置方法。 Condition class implements conditio…

Java BigInteger类| hashCode()方法与示例

BigInteger类hashCode()方法 (BigInteger Class hashCode() method) hashCode() method is available in java.math package. hashCode()方法在java.math包中可用。 hashCode() method is used to return the hash code value of this BigInteger. hashCode()方法用于返回此Big…

认真聊一下MySQL索引的底层实现!

前言当我们发现SQL执行很慢的时候,自然而然想到的就是加索引,当然他也是高频的面试问题,所以今天我们一起来学习一下MySQL索引的底层实现:B树。树简介、树种类B-树、B树简介B树插入B树查找B树删除B树经典面试题树的简介树的简介树…

js的四舍五入

Math.ceil求最小的整数但不小于本身. Math.round求本身的四舍五入。 Math.floor求最大的整数但不大于本身.

Java BigInteger类| bitCount()方法与示例

BigInteger类的bitCount()方法 (BigInteger Class bitCount() method) bitCount() method is available in java.math package. bitCount()方法在java.math包中可用。 bitCount() method is used to count the number of bits in 2’s complement denotation of this BigIntege…

head first python(第三章)–学习笔记

1.介绍基础文件,输入,输出 open() 打开文件,一次传入一行数据,可以结合for循环和readline()来使用 close() 用来关闭open打开的文件 the_file open(sketch.txt)the_file.close()例子: >>> data open(/root/…

最新大厂面试真题集锦

年后又是一波求职季,正是“金三银四”这个求职黄金期,很多人扎堆在这个时间段跳槽,找工作,程序员也不例外。春节刚过,各公司企业都开始启动了新一年的招聘计划,招聘岗位倍增,求职人数远超于岗位…

java.lang.IllegalThreadStateException 线程运行报错

写程序线程再运行第二遍的时候报java.lang.IllegalThreadStateException。发现一个Thread不能重复用start方法。 解决方法: 1、将extends Thread线程类改成implements Runnable,或者将Thread a new Thread改为Runnable a new Runnable; …

使用OpenCV在Python中进行人脸和眼睛检测

Modules Used: 使用的模块: python-opencv(cv2)python-opencv(cv2) python-opencv(cv2) Opencv(Open source computer vision) is a python library that will help us to solve computer vision problems. Opencv(开源计算机视觉)是一个Python库,可帮…

Java打造一款SSH客户端,已开源!

最近由于项目需求,项目中需要实现一个WebSSH连接终端的功能,由于自己第一次做这类型功能,所以首先上了GitHub找了找有没有现成的轮子可以拿来直接用,当时看到了很多这方面的项目,例如:GateOne、webssh、she…

html中可以自定义属性,,,妈的竟然才知道..

html中可以自定义属性,,,妈的竟然才知道.. <input userinfo"没见过帅哥呀" />

Js实现动态插入删除文本框

自己做了个Js插入文本框的例子&#xff0c;扔上别忘了。 <html><head><title>Untitled Document</title><meta http-equiv"Content-Type" content"text/html; charsetutf-8"><script language"javascript"&g…

ruby 数组元素替换_从Ruby中的集合中删除并替换元素

ruby 数组元素替换Ruby has various specific methods to fulfil specific tasks. At several places, you may need to replace or delete an element from an instance of set class provided that there are certain elements present in the Set. You can perform deletion…

我去,这几个Linux指令太装B了|动图展示

1. sl先看一下呼啸而过的火车&#xff1b;安装指令如下&#xff1b;sduo apt-get install sl执行结果如下&#xff1a;2. htop图形化Linux系统性能监测工具&#xff0c;屌不屌:安装指令如下:sduo apt-get install htop执行结果如下&#xff1b;3. gcp以前用cp复制文件总是看不懂…

书店POS机--细化迭代2--测试

2019独角兽企业重金招聘Python工程师标准>>> (1) 开始一次新的销售&#xff0c;点击书店POS系统的销售&#xff1a; (2) 进入销售模块之后的界面如下&#xff1a; (3)逐条录入商品条目(根据商品编号)&#xff0c;并修改数量。确认无误之后点击“确认”按钮&#x…

XML文件的写入和读取(解析)基于DOM4J工具

这两天做了个天气的小应用&#xff0c;需要用到百度的天气api&#xff0c;获取到的信息是一个xml文档。 所以就从网上查了一下相关的知识&#xff0c;就是关于怎么去解析出来xml文件的信息。 先放一个我自己写的例子&#xff0c;加了点注释&#xff0c;贴这里吧。 package cn…

Google Guava,牛逼的脚手架

01、前世今生你好呀&#xff0c;我是 Guava。1995 年的时候&#xff0c;我的“公明”哥哥——Java 出生了。经过 20 年的发展&#xff0c;他已经成为世界上最流行的编程语言了&#xff0c;请允许我有失公允的把“之一”给去了。虽然他时常遭受着各种各样的吐槽&#xff0c;但他…

ruby 将字符转数字计算_Ruby程序计算一个数字中的位数

ruby 将字符转数字计算计算位数 (Counting the number of digits) Ruby does not provide you any predefined direct method through which you can find the number of digits in a number. Though one method can be implemented by converting the number into a string an…

python_L2_operator

1. i/j – division – if both are ints, result is int, represen9ng quo9ent without remainder e.g. 3/2 1 3.0/2 1.5  but   -3/2 -2 2. --2 >>> 2 3. a * 2 >>> aa 4 . abc[-1] returns c 5. world[:-1] returns worl转载于:https://www.cnbl…

Android Call requires API level 11 (current min is 8)的解决方案

【错误描述】 在用Eclipse开发过程中&#xff0c;为了兼容Android2.2和4.0以上版本&#xff0c;我在使用Notification类时做了2个版本的代码&#xff0c;代码根据系统版本不同执行相应模块&#xff0c;结果&#xff0c;等我输完代码&#xff0c;发现系统提示了一个这么的错误。…