面试官:Spring事务什么时候会失效?

应聘者:

  • 访问权限问题

  • 方法用final修饰

  • 未被Spring管理

  • 错误的传播特性

  • 自己吞了异常

  • 手动抛了别的异常

  • 自定义了回滚异常

  • 方法内部调用

1、访问权限问题

Java的访问权限主要有三种:private、protected、public,它们的权限从左到右,依次变大。但如果我们在开发过程中,把有某些事务方法,定义了错误的访问权限,就会导致事务功能出问题,例如:

1 @Service
2 public class OrderService {
3 @Transactional
4 private void add(OrderVO orderVO) {
5 saveData(orderVO);
6 }
7 }

从上面可以看到add方法的访问权限是private修饰的,这样会导致事务失效,spring要求被代理方法必须是public的,事务会失效。

2、方法final修饰的

当某个方法被final修饰时,子类是无法继承和重载的,事务是基于动态代理去实现的,如果某个方法用final修饰了,那么在它的代理类中,就无法重写该方法,而添加事务功能。

1 @Service
2 public class OrderService {
3 @Transactional
4 public final void add(OrderVO orderVO) {
5 saveData(orderVO);
6 }
7 }

3、未被Spring管理

使用spring事务的前提是:对象要被spring管理,需要创建bean实例。如果,你开发了一个Service类,但忘了加@Service注解,比如:

1 //@Service
2 public class OrderService {
3 @Transactional
4 public final void add(OrderVO orderVO) {
5 saveData(orderVO);
6 }
7 }

又或者XML里面配置纳入Spring管理的包文件路径配置错误等。

4、错误的传播特性

我们在使用@Transactional注解时,是可以指定propagation参数的。该参数的作用是指定事务的传播特性,spring目前支持7种传播特性:

  • REQUIRED:如果当前上下文中存在事务,那么加入该事务,如果不存在事务,创建一个事务,这是默认的传播属性值;

  • SUPPORTS:如果当前上下文存在事务,则支持事务加入事务,如果不存在事务,则使用非事务的方式执行;

  • MANDATORY:如果当前上下文中存在事务,否则抛出异常;

  • REQUIRES_NEW:每次都会新建一个事务,并且同时将上下文中的事务挂起,执行当前新建事务完成以后,上下文事务恢复再执行;

  • NOT_SUPPORTED:如果当前上下文中存在事务,则挂起当前事务,然后新的方法在没有事务的环境中执行;

  • NEVER:如果当前上下文中存在事务,则抛出异常,否则在无事务环境上执行代码;

  • NESTED:如果当前上下文中存在事务,则嵌套事务执行,如果不存在事务,则新建事务;

如果我们在手动设置propagation参数的时候,把传播特性设置错了,比如:

1 @Service
2 public class OrderService {
3 @Transactional(propagation = Propagation.NEVER)
4 public void add(OrderVO orderVO) {
5 saveData(orderVO);
6 }

5、自己吞了异常

事务不会回滚,最常见的问题是:开发者在代码中手动try...catch了异常。比如:

 1 @Service
2 public class OrderService {
3 @Transactional
4 public void add(OrderVO orderVO) {
5 try{
6 saveData(orderVO);
7 } catch(Exception e) {
8 log.error(e);
9 }
10 }
11 }

这种情况下spring事务当然不会回滚,因为开发者自己捕获了异常,又没有手动抛出,换句话说就是把异常吞掉了。

如果想要spring事务能够正常回滚,必须抛出它能够处理的异常。如果没有抛异常,则spring认为程序是正常的。

6、手动抛了别的异常

即使开发者没有手动捕获异常,但如果抛的异常不正确,spring事务也不会回滚。

 1 @Service
2 public class OrderService {
3 @Transactional
4 public void add(OrderVO orderVO) {
5 try{
6 saveData(orderVO);
7 } catch(Exception e) {
8 log.error(e);
9 throw new Exception(e);
10 }
11 }
12 }

上面的这种情况,开发人员自己捕获了异常,又手动抛出了异常:Exception,事务同样不会回滚。因为spring事务,默认情况下只会回滚RuntimeException(运行时异常)和Error(错误),对于普通的Exception(非运行时异常),它不会回滚。

7、自定义了回滚异常

@Transactional注解声明事务时,有时我们想自定义回滚的异常,spring也是支持的。可以通过设置rollbackFor参数,来完成这个功能。

1 @Service
2 public class OrderService {
3 @Transactional(rollbackFor = BusinessException.class)
4 public void add(OrderVO orderVO) {
5 saveData(orderVO);
6 }
7 }

如果在执行上面这段代码,保存和更新数据时,程序报错了,抛了SqlException、NullPointerException等异常。而BusinessException是我们自定义的异常,报错的异常不属于BusinessException,所以事务也不会回滚。

8、方法内部调用

有时候我们需要在某个Service类的某个方法中,调用另外一个事务方法,比如:

 1 @Service
2 public class OrderService {
3 @Transactional
4 public void add(OrderVO orderVO) {
5 saveData(orderVO);
6 }
7
8 @Transactional
9 public void saveData(OrderVO orderVO) {
10 doSameThing();
11 }
12 }

我们看到在事务方法add中,直接调用事务方法saveData。saveData方法拥有事务的能力是因为Spring Aop生成代理了对象,但是这种方法直接调用了this对象的方法,所以saveData方法不会生成事务。

由此可见,在同一个类中的方法直接内部调用,会导致事务失效。

Spring事务什么时候会失效?的更多相关文章

  1. 聊聊Spring事务控制策略以及@Transactional失效问题避坑

    大家好,又见面了. 在大部分涉及到数据库操作的项目里面,事务控制.事务处理都是一个无法回避的问题.比如,需要对SQL执行过程进行事务的控制与处理的时候,其整体的处理流程会是如下的示意: 首先是要开启事 ...

  2. java面试记录二:spring加载流程、springmvc请求流程、spring事务失效、synchronized和volatile、JMM和JVM模型、二分查找的实现、垃圾收集器、控制台顺序打印ABC的三种线程实现

    注:部分答案引用网络文章 简答题 1.Spring项目启动后的加载流程 (1)使用spring框架的web项目,在tomcat下,是根据web.xml来启动的.web.xml中负责配置启动spring ...

  3. Spring事务失效的原因

    http://blog.csdn.net/paincupid/article/details/51822599 Spring事务失效的原因 5种大的原因 如使用mysql且引擎是MyISAM,则事务会 ...

  4. Spring事务失效的2种情况

    使用默认的事务处理方式 因为在java的设计中,它认为不继承RuntimeException的异常是”checkException”或普通异常,如IOException,这些异常在java语法中是要求 ...

  5. Spring事务注解@Transactional失效的问题

    在项目中发现事务失效,使用@Transactional注解标注的Service业务层实现类方法全部不能回滚事务了,最终发现使用因为Spring与shiro进行整合之后导致的问题,将所有的Service ...

  6. Spring事务Transactional和动态代理(三)-事务失效的场景

    系列文章索引: Spring事务Transactional和动态代理(一)-JDK代理实现 Spring事务Transactional和动态代理(二)-cglib动态代理 Spring事务Transa ...

  7. Spring事务深入剖析--spring事务失效的原因

    之前我们讲的分布式事务的调用都是在一个service中的事务方法,去调用另外一个service中的业务方法, 如果在一个sevice中存在两个分布式事务方法,在一个seivice中两个事务方法相互嵌套 ...

  8. 就这?Spring 事务失效场景及解决方案

    小明:靓仔,我最近遇到了很邪门的事. 靓仔:哦?说来听听. 小明:上次看了你的文章<就这?一篇文章让你读懂 Spring 事务>,对事务有了详细的了解,但是在项目中还是遇到了问题,明明加了 ...

  9. 聊聊spring事务失效的12种场景,太坑了

    前言 对于从事java开发工作的同学来说,spring的事务肯定再熟悉不过了. 在某些业务场景下,如果一个请求中,需要同时写入多张表的数据.为了保证操作的原子性(要么同时成功,要么同时失败),避免数据 ...

随机推荐

  1. [loj3339]美食家

    令$f[i][j]$表示第$i$个时刻走到点$j$的最小时间,暴力的$dp$复杂度为$o(tm)$ 如果没有限制,由于$w\le 5$,记录前5个时刻的状态即可求出当前状态,用矩阵乘法可优化到$o(n ...

  2. 当 dotnet-monitor 遇上 Prometheus, 是种什么样的体验?

    对于开发和运维人员来说, 监控大屏很棒, 让我们来做一个 Dashboard 吧! 大家可能听说过一些 CLI 诊断工具, 比如 dotnet-counters,dotnet-dump 和 dotne ...

  3. Redis | 第7章 Redis 服务器《Redis设计与实现》

    目录 前言 1. 命令请求的执行过程 1.1 发送命令请求 1.2 读取命令请求 1.3 命令执行器(1):查找命令实现 1.4 命令执行器(2):执行预备操作 1.5 命令执行器(3):调用命令的实 ...

  4. FMT 和 子集卷积

    FMT 和 子集卷积 FMT 给定数列 $ a_{0\dots 2^{k}-1} $ 求 $ b $ 满足 $ b_{s} = \sum_{i\in s} a_i $ 实现方法很简单, for( i ...

  5. R语言与医学统计图形-【11】ggplot2几何对象之散点图

    ggplot2绘图系统--几何对象之散点图 以geom开头的函数超过30个.几何对象和标度函数scale密不可分.只有在aes中传入某个变量,scale才能发挥作用. 所谓标度scale,就是图形遥控 ...

  6. Docker实用命令介绍

    Docker实用命令介绍 1. docker启动.关闭.停止 ╭─wil-xz in ~ 12:15:44 ╰─٩(ŏ﹏ŏ.)۶ service docker restart Redirecting ...

  7. BAT的一些题

    114.java中实现多态的机制是什么 答:重写,重载.方法的重写Overriding和重载Overloading是Java多态性的不同表现.  重写Overriding是父类与子类之间多态性的一种表 ...

  8. Hive-insert into table 与 insert overwrite table 区别

    区分insert into 和 insert overowrite: 0. 命令格式 INSERT OVERWRITE|INTO TABLE tablename [PARTITION (partcol ...

  9. Redis集合解决大数据筛选

    Redis集合:集合是什么,就是一堆确定的数据放在一起,数学上集合有交集.并集的概念,这个就可以用来做大数据的筛选功能. 以商品为例,假如商品有颜色和分类.价格区间等属性. 给所有统一颜色的商品放一个 ...

  10. 22-reverseString-Leetcode

    思路:so easy class Solution { public: string reverseString(string s) { int n = s.size(); for(int i=0;i ...