java笔记java中@Transactional注解的使用及其失效情景
Posted 棉花糖灬
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java笔记java中@Transactional注解的使用及其失效情景相关的知识,希望对你有一定的参考价值。
本文转自文章一口气说出 6种,@Transactional注解的失效场景。
一、事务
spring中的事务管理机制可以分为编程式事务和声明式事务两种。
- 编程式事务:指在代码中手动的管理事务的提交、回滚等操作,代码侵入性比较强。
- 声明式事务: 基于AOP面向切面的,它将具体业务与事务处理部分解耦,代码侵入性很低,所以在实际开发中声明式事务用的比较多。声明式事务也有两种实现方式,是基于TX和AOP的xml配置文件方式,二种就是基于
@Transactional
注解了。
二、@Transactional注解
1. 用法
@Transactional
注解可以作用在类、接口、方法上。
- 作用于类:表示该类的所有public方法都配置了事务。
- 作用于接口:不推荐这种使用方法,因为一旦标注在Interface上并且配置了Spring AOP 使用CGLib动态代理,将会导致@Transactional注解失效。
- 作用于方法:当类配置了@Transactional,方法也配置了@Transactional,方法的事务会覆盖类的事务配置信息。
2. @Transactional的属性
(1) propagation属性
表示事务的传播行为,其取值如下:
Propagation.REQUIRED
:如果当前存在事务,则加入该事务,如果当前不存在事务,则创建一个新的事务。 为默认值。Propagation.SUPPORTS
:如果当前存在事务,则加入该事务;如果当前不存在事务,则以非事务的方式继续运行。Propagation.MANDATORY
:如果当前存在事务,则加入该事务;如果当前不存在事务,则抛出异常。Propagation.REQUIRES_NEW
:重新创建一个新的事务,如果当前存在事务,暂停当前的事务。Propagation.NOT_SUPPORTED
:以非事务的方式运行,如果当前存在事务,暂停当前的事务。Propagation.NEVER
:以非事务的方式运行,如果当前存在事务,则抛出异常。Propagation.NESTED
:和Propagation.REQUIRED
效果一样。
(2) isolation属性
表示事务的隔离级别,其取值如下:
solation.DEFAULT
:使用底层数据库默认的隔离级别。为默认值。Isolation.READ_UNCOMMITTED
:未提交读。Isolation.READ_COMMITTED
:提交读。Isolation.REPEATABLE_READ
:可重复读。Isolation.SERIALIZABLE
:序列化。
(3) timeout属性
事务的超时时间,默认为-1。如果超过该时间限制但事务还没有完成,则自动回滚事务。
(4) readOnly属性
指定事务是否为只读事务,默认值为false,当为true时可以忽略那些不需要事务的方法,如读取数据。
(5) rollbackFor属性
用于指定能够触发事务回滚的异常类型,可以指定多个异常类型。
(6) noRollbackFor属性
抛出指定的异常类型,不回滚事务,可以指定多个异常类型。
3. @Transactional失效的场景
(1) 应用在非public 方法上时
protected
、private
修饰的方法上使用@Transactional
注解,虽然事务无效,但不会有任何报错。
(2) propagation属性设置错误
若是错误的配置以下三种 propagation,事务将不会发生回滚:
Propagation.SUPPORTS
:如果当前存在事务,则加入该事务;如果当前不存在事务,则以非事务的方式继续运行。Propagation.NOT_SUPPORTED
:以非事务的方式运行,如果当前存在事务,暂停当前的事务。Propagation.NEVER
:以非事务的方式运行,如果当前存在事务,则抛出异常。
(3) rollBackFor属性设置错误
Spring默认抛出了未检查unchecked异常(继承自 RuntimeException 的异常)或者 Error才回滚事务;其他异常不会触发回滚事务。如果在事务中抛出其他类型的异常,但却期望 Spring 能够回滚事务,就需要指定rollbackFor属性。
(4) 调用同一个类中的方法时
如果类中的方法A()调用同一个类中的方法B(),且方法A()没有声明事务,而方法B()声明了事务,那么在外部调用方法A()时,方法B()的事务是无效的。
这是由于使用Spring AOP代理造成的,因为只有当事务方法被当前类以外的代码调用时,才会由Spring生成的代理对象来管理。
(5) 异常被catch捕获导致注解失效
在方法A()上加了@Transactional注解,同时A()方法中调用方法B(),若方法B()抛出的异常被A()方法的catch捕获时,事务将不能正常回滚。
处理方法为:在catch块中再把注解中指定的异常抛出,若没指定异常,则可以抛出throw new RuntimeException()
。或者直接不用try-catch代码块。
(6) 数据库引擎不支持事务
常用的mysql数据库默认使用支持事务的innodb引擎。一旦数据库引擎切换成不支持事务的myisam,那事务就从根本上失效了。
以上是关于java笔记java中@Transactional注解的使用及其失效情景的主要内容,如果未能解决你的问题,请参考以下文章
Java Spring @Transactional 防止并发