面试一口气说出Spring的声明式事务@Transactional注解的6种失效场景

一、Spring事务管理的两种方式

事务管理在系统开发中是不可缺少的一部分,Spring提供了很好事务管理机制,主要分为编程式事务声明式事务两种。

编程式事务:是指在代码中手动的管理事务的提交、回滚等操作,代码侵入性比较强,如下示例:

声明式事务:是建立在AOP之上的,其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。

最大的优点就是不需要通过编程的方式管理事务,这样就不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明(或通过基于@Transactional注解的方式),便可以将事务规则应用到业务逻辑中。

显然声明式事务管理要优于编程式事务管理,这正是spring倡导的非侵入式的开发方式。声明式事务管理使业务代码不受污染,一个普通的POJO对象,只要加上注解就可以获得完全的事务支持。

和编程式事务相比,声明式事务唯一不足地方是,它的最细粒度只能作用到方法级别,无法做到像编程式事务那样可以作用到代码块级别。

声明式事务也有两种实现方式,

基于TX和AOP的xml配置文件方式
基于@Transactional注解

 

 

二、@Transactional注解介绍

1、@Transactional注解可以作用于哪些地方?

@Transactional 可以作用在接口、类、类方法。

作用于类:当把@Transactional 注解放在类上时,表示所有该类的public方法都配置相同的事务属性信息。

作用于方法:当类配置了@Transactional,方法也配置了@Transactional,方法的事务会覆盖类的事务配置信息。

作用于接口:不推荐这种使用方法,因为一旦标注在Interface上并且配置了Spring AOP 使用CGLib动态代理,将会导致@Transactional注解失效。

2、@Transactional注解有哪些属性?

propagation属性

事务的传播行为,默认值为 Propagation.REQUIRED,属性信息如下:

Propagation.REQUIRED:如果当前存在事务,则加入该事务,如果当前不存在事务,则创建一个新的事务。( 也就是说如果A方法和B方法都添加了注解,在默认传播模式下,A方法内部调用B方法,会把两个方法的事务合并为一个事务 )

Propagation.SUPPORTS:如果当前存在事务,则加入该事务;如果当前不存在事务,则以非事务的方式继续运行。

Propagation.MANDATORY:如果当前存在事务,则加入该事务;如果当前不存在事务,则抛出异常。

Propagation.REQUIRES_NEW:重新创建一个新的事务,如果当前存在事务,暂停当前的事务。( 当类A中的 a 方法用默认Propagation.REQUIRED模式,类B中的 b方法加上采用 Propagation.REQUIRES_NEW模式,然后在 a 方法中调用 b方法操作数据库,然而 a方法抛出异常后,b方法并没有进行回滚,因为Propagation.REQUIRES_NEW会暂停 a方法的事务 )

Propagation.NOT_SUPPORTED:以非事务的方式运行,如果当前存在事务,暂停当前的事务。

Propagation.NEVER:以非事务的方式运行,如果当前存在事务,则抛出异常。

Propagation.NESTED:和 Propagation.REQUIRED 效果一样。

isolation 属性

事务的隔离级别,默认值为 Isolation.DEFAULT。

Isolation.DEFAULT:使用底层数据库默认的隔离级别。

Isolation.READ_UNCOMMITTED :未提交读

Isolation.READ_COMMITTED :已提交读

Isolation.REPEATABLE_READ :可重复读

Isolation.SERIALIZABLE :串型化

timeout 属性

事务的超时时间,默认值为 -1。如果超过该时间限制但事务还没有完成,则自动回滚事务。

readOnly 属性

指定事务是否为只读事务,默认值为 false;为了忽略那些不需要事务的方法,比如读取数据,可以设置 read-only 为 true。

rollbackFor 属性

用于指定能够触发事务回滚的异常类型,可以指定多个异常类型。

noRollbackFor属性

抛出指定的异常类型,不回滚事务,也可以指定多个异常类型。

 

三、@Transactional的6种失效场景

1、@Transactional 应用在非 public 修饰的方法上
如果Transactional注解应用在非 public 修饰的方法上,Transactional将会失效。

是因为在Spring AOP 代理时,TransactionInterceptor (事务拦截器)在目标方法执行前后进行拦截,DynamicAdvisedInterceptor(CglibAopProxy 的内部类)的intercept方法 或 JdkDynamicAopProxy的invoke方法会间接调用AbstractFallbackTransactionAttributeSource的 computeTransactionAttribute方法,获取Transactional 注解的事务配置信息。


此方法会检查目标方法的修饰符是否为 public,不是 public则不会获取@Transactional 的属性配置信息。

注意:protected、private 修饰的方法上使用 @Transactional 注解,虽然事务无效,但不会有任何报错,这是我们很容易犯错的一点。

2、@Transactional 注解属性 propagation 设置错误
这种失效是由于配置错误,若是错误的配置以下三种 propagation,事务将不会发生回滚。

TransactionDefinition.PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。

TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。

TransactionDefinition.PROPAGATION_NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。

3、@Transactional 注解属性 rollbackFor 设置错误
rollbackFor 可以指定能够触发事务回滚的异常类型。Spring默认抛出了未检查unchecked异常(继承自 RuntimeException的异常)或者 Error才回滚事务,其他异常不会触发回滚事务。

若在目标方法中抛出的异常是 rollbackFor 指定的异常的子类,事务同样会回滚。

4、同一个类中方法调用,导致@Transactional失效

开发中避免不了会对同一个类里面的方法调用,比如有一个类Test,它的一个方法A,A再调用本类的方法B(不论方法B是用public还是private修饰),但方法A没有声明注解事务,而B方法有。则外部调用方法A之后,方法B的事务是不会起作用的。这也是经常犯错误的一个地方。

那为啥会出现这种情况?其实这还是由于使用Spring AOP代理造成的,因为只有当事务方法被当前类以外的代码调用时,才会由Spring生成的代理对象来管理。

 

5、异常被catch捕获导致@Transactional失效

这种情况是最常见的一种@Transactional注解失效场景

如果B方法内部抛了异常,而A方法此时try catch了B方法的异常,那这个事务就不能正常回滚了,会抛出异常:

因为当ServiceB中抛出了一个异常以后,ServiceB标识当前事务需要rollback。但是ServiceA中由于你手动的捕获这个异常并进行处理,ServiceA认为当前事务应该正常commit。此时就出现了前后不一致,也就是因为这样,抛出了前面的UnexpectedRollbackException异常。

spring的事务是在调用业务方法之前开始的,业务方法执行完毕之后才执行commit or rollback,事务是否执行取决于是否抛出runtime异常。如果抛出runtime exception 并在你的业务方法中没有catch到的话,事务会回滚。

在业务方法中一般不需要catch异常,如果非要catch一定要抛出throw new RuntimeException(),或者注解中指定抛异常类型@Transactional(rollbackFor=Exception.class),否则会导致事务失效,数据commit造成数据不一致,所以有些时候try catch反倒会画蛇添足。

6、数据库引擎不支持事务

这种情况出现的概率并不高,事务能否生效数据库引擎是否支持事务是关键。常用的MySQL数据库默认使用支持事务的innodb引擎,一旦数据库引擎切换成不支持事务的myisam,那事务就从根本上失效了

 

 
  1.  

 

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

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

相关文章

JAVA断点调试

1、条件断点,点击添加条件 2、异常断点,点击添加异常 转载于:https://www.cnblogs.com/binbang/p/6378897.html

操作系统:Win10如何彻底卸载自带的Flash软件

Win10操作系统中,Flash功能是系统自带的,我们无法直接通过应用管理来找到Flash,所以也不能从系统设置或者控制面板中卸载它。当然如果你是后期自己安装的话,可以通过控制面板找到Flash然后直接卸载它。 Flash的路径为“C:\Windows…

Java运行时异常和非运行时异常

1.Java异常机制 Java把异常当做对象来处理,并定义一个基类java.lang.Throwable作为所有异常的超类。Java中的异常分为两大类:错误Error和异常Exception,Java异常体系结构如下图所示 2.Throwable Throwable类是所有异常或错误的超类&#xf…

办公技巧:如何快速提取办公文档里面的所有图片

针对一个比较大的办公文档里面有很多图片,有些时候我们需要提取文档里面的所有图片信息,当然你打开文档一个个复制保存就可以了,不过这样太过于繁琐了,有没有更加快速的方法呢?今天给大家分享快速提取办公文档里面的所…

ELK+Filebeat+Kafka+ZooKeeper 构建海量日志分析平台(elk5.2+filebeat2.11)

ELKFilebeatKafkaZooKeeper 构建海量日志分析平台 参考:http://www.tuicool.com/articles/R77fieA 我在做ELK日志平台开始之初选择为ELKRedis直接构建,在采集nginx日志时一切正常,当我采集我司业务报文日志类后,logstash会报大量的…

Spring回滚事务类型

Spring默认抛出了未检查unchecked异常(继承自 RuntimeException的异常)或者 Error才回滚事务,其他异常不会触发回滚事务。

操作系统:Win10操作系统内置的备份功能介绍

今天给大家分享Win10操作系统内置的系统备份功能,感兴趣的可以了解一下!。 Win10的备份:由“旧版备份与还原”、“还原点”和“文件历史记录”三个部分组成。 旧版备份与还原:主要用于系统备份与还原 还原点:还原点 文…

spring 事务控制 设置手动回滚 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

如上: 当我们需要在事务控制的service层类中使用try catch 去捕获异常后,就会使事务控制失效,因为该类的异常并没有抛出,就不是触发事务管理机制。怎样才能即使用try catch去捕获异常,而又让出现异常后spring回滚呢&am…

电脑软件:推荐一款本地文档搜索神器,赶快下载试试吧!

1、前言大家在日常办公的时候,经常会涉及各种各样的文档,时间久了文件会越来越多,有时候需要快速找到一个半年前文档可能会耗费你的大量时间,毕竟每个人的大脑记忆都是有限的,不可能每个细节都能够靠大脑记忆&#xff…

JVM系列(一):JVM基本概念知识笔记

今天开始给大家分享JVM系列知识,欢迎大家一起学习交流共同进度! 1、什么是JVM? JVM即Java虚拟机,可以理解为一种抽象计算机,它拥有一个指令集,在运行时操作各种内存区域。JVM对Java语言一无所知&#xff0…

配置maven环境变量cmd控制台提示:mvn不是内部或外部命令,也不是可运行的程序或批处理文件...

配置maven环境变量cmd控制台提示:mvn不是内部或外部命令,也不是可运行的程序或批处理文件 首先maven环境变量: 变量名:MAVEN_HOME 变量值:E:\apache-maven-3.2.3 变量名:Path 变量值:;%MVN_HOME…

电脑技巧:Win10任务管理器知识介绍,赶快来看一看吧

Win10操作系统的任务管理器应该是大家比较熟悉的软件,尤其是在你的电脑卡掉的时候,不得不打开任务管理器,结束掉进程卡死的进程,然后电脑就可以恢复正常使用,任务管理器作为Windows操作系统上一款使用频率非常高的软件…

[转]Asp.Net大型项目实践(11)-基于MVC Action粒度的权限管理【续】【源码在这里】(在线demo,全部源码)...

本文转自:http://www.cnblogs.com/legendxian/archive/2010/01/25/1655551.html 接上篇Asp.Net大型项目实践(10)-基于MVC Action粒度的权限管理(在线demo,全部源码) 在线Demo: 地址:http://218.60.8.35:1234/ 服务器&a…

电脑软件:推荐八款电脑必备效率软件

目录 1、PowerToys 微软官方效率神器 2、Ditto 剪切板神器 3、AnyTXT Searcher 文本搜索神器 4、Everything 文件检索神器 5、Monitorian 屏幕亮度调节神器 Monitorian 是一款超级实用的屏幕亮度调节工具,可以在任务栏以滑杆的方式调节屏幕亮度,且…

JVM系列(二):JVM中类加载器相关知识笔记

今天继续给大家分享JVM相关的知识,欢迎互相沟通交流! 1、什么是类的加载和类的卸载 JVM虚拟机运行的文件是class文件,它是由我们的Java程序编译后产生的文件。 类的加载:JVM虚拟机将指定的class文件读取到内存里,并…

JVM系列(三):双亲委派机制笔记

今天给大家分享JVM系列之双亲委派机制相关的知识。 1、Java类加载的过程 Java类的加载过程是动态的,它不会一次性把程序所有的类全部加载后再运行,而是先保障程序运行的基础类加载到JVM虚拟机当中,其他的类,一般是再需要的时候才…