1、事务介绍

事务管理在系统开发中是不可缺少的一部分,Spring提供了很好事务管理机制,主要分为编程式事务和声明式事务两种。
编程式事务:是指在代码中手动的管理事务的提交、回滚等操作,代码侵入性比较强,如下示例:

try  {     transactionManager.commit(status);
}  catch (Exception e)  {     transactionManager.rollback(status);     throw new InvoiceApplyException("异常失败");
}

声明式事务:基于AOP面向切面的,它将具体业务与事务处理部分解耦,代码侵入性很低,所以在实际开发中声明式事务用的比较多。
声明式事务也有两种实现方式,一是基于TX和AOP的xml配置文件方式,二种就是基于@Transactional注解了,如

@Transactional
@GetMapping("/addCity")
public String add()  {     int result = cityMapper.insert(cityInfo);
}

2、@Transactional介绍

1、@Transactional注解可以作用于哪些地方?
@Transactional 可以作用在接口、类、类方法。
作用于类:当把@Transactional 注解放在类上时,表示所有该类的public方法都配置相同的事务属性信息。
作用于方法:当类配置了@Transactional,方法也配置了@Transactional,方法的事务会覆盖类的事务配置信息。
作用于接口:不推荐这种使用方法,因为一旦标注在Interface上并且配置了Spring AOP 使用CGLib动态代理,将会导致@Transactional注解失效
2、@Transactional注有哪些属性?
propagation属性
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 :事务的隔离级别,默认值为 Isolation.DEFAULT。
Isolation.DEFAULT:使用底层数据库默认的隔离级别。
Isolation.READ_UNCOMMITTED 读未提交
Isolation.READ_COMMITTED 读已提交
Isolation.REPEATABLE_READ 不可重复读
Isolation.SERIALIZABLE 串行化
timeout 属性
timeout :事务的超时时间,默认值为 -1。如果超过该时间限制但事务还没有完成,则自动回滚事务。
readOnly 属性
readOnly :指定事务是否为只读事务,默认值为 false;为了忽略那些不需要事务的方法,比如读取数据,可以设置 read-only 为 true。
rollbackFor 属性
rollbackFor :用于指定能够触发事务回滚的异常类型,可以指定多个异常类型。
noRollbackFor属性
noRollbackFor:抛出指定的异常类型,不回滚事务,也可以指定多个异常类型。

3、@Transactional失效场景

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

2、@Transactional 注解属性 propagation 设置错误
这种失效是由于配置错误,若是错误的配置以下三种 propagation,事务将不会发生回滚。
TransactionDefinition.PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。
TransactionDefinition.PROPAGATION_NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。

**3、错误异常,导致失效@Transactional **
rollbackFor 可以指定能够触发事务回滚的异常类型。Spring默认抛出了未检查unchecked异常(继承自 RuntimeException 的异常)或者 Error才回滚事务,其他异常不会触发回滚事务(包括try catch吞了异常)。如果在事务中抛出其他类型的异常,但却期望 Spring 能够回滚事务,就需要指定rollbackFor属性,踩过坑的有当时间转换错误时抛出的异常ParseException 它不是RuntimeException 下异常则不会被回滚。

4、同一个类中方法调用,导致@Transactional失效
开发中避免不了会对同一个类里面的方法调用,比如有一个类Test,它的一个方法A,A再调用本类的方法B(不论方法B是用public还是private修饰),但方法A没有声明注解事务,而B方法有。当外界调用方法A之后,方法B的事务是不会起作用的。这也是经常犯错误的一个地方。那为什么会出现这种情况?其实这还是由于使用Spring AOP代理造成的,因为只有当事务方法被当前类以外的代码调用时,才会由Spring生成的代理对象来管理。

5、多线程调用,导致@Transactional失效
spring的事务是通过数据库连接来实现的。当前线程中保存了一个map,key是数据源,value是数据库连接。
源码:private static final ThreadLocal<Map<Object, Object>> resources = new NamedThreadLocal<>(“Transactional resources”);
我们说的同一个事务,其实是指同一个数据库连接,只有拥有同一个数据库连接才能同时提交和回滚。如果在不同的线程,拿到的数据库连接肯定是不一样的,所以是不同的事务。如 在方法A中使用多线程调用方法B,如果方法B报错了,则方法A事务是不会回滚。

Spring事务注解介绍相关推荐

  1. Spring事务注解

    ​ 一.事务特性 @Transactional注解是用于事务控制的,需要知道事务的ACID特征:即原子性(Atomicity,或称不可分割性).一致性(Consistency).隔离性(Isolati ...

  2. Spring——事务注解@Transactional【建议收藏】

    在某些业务场景下,如果一个请求中,需要同时写入多张表的数据或者执行多条sql,为了保证操作的原子性(要么同时成功,要么同时失败),避免数据不一致的情况,我们一般都会用到事务:Spring框架下,我们经 ...

  3. Spring事务注解实现的原理

    Spring事务注解是个典型的Spring AOP的注解.方法上面加上@Transactional,方法就有了事务的能力. 面试中:基于动态代理讲更多的东西.... 为什么呢?--->其实里面核 ...

  4. Spring——事务注解@Transactional的源码分析

    本篇结合我的这篇<Spring事务注解@Transactional>,为第二节[2.Spring声明式事务的原理]的详细说明,debug了被@Transactional包裹的目标方法所在类 ...

  5. dubbo 注解与spring 事务注解冲突完美解决方案

    这几天碰到dubbo 注解与spring 事务注解同时启用dubbo注解无法生效的问题. 在网上找了大部分程序员们贴出的解决方案都没有解决问题.最终在自己的分析下成功解决问题. 解决步骤如下,后面会贴 ...

  6. MySQL事务隔离级别和Spring事务关系介绍

    事务隔离级别介绍 隔离级别 脏读 不可重复读 幻读 未提交读(Read uncommitted) 可能 可能 可能 已提交读(Read committed) 不可能 可能 可能 可重复读(Repeat ...

  7. spring事务注解@Transactional参数详解

    在Spring中进行事务管理操作有两种方式:编程式事务管理和声明式事务管理.这里介绍的是第二种方式. 1.声明式事务管理(底层使用AOP原理): 1>基于注解方式.(本文章基于注解) 2> ...

  8. Spring事务注解配置

    一,spring基于注解式的事务配置方法:@Transactional 1.xml配置 <?xml version="1.0" encoding="UTF-8&qu ...

  9. 三木之Spring事务注解实现

    AOP底层实现原理 动态代理 ( 什么是动态代理 1.代理对象,不需要实现接口 2.代理对象的生成,是利用JDK的API,动态的在内存中构建代理对象(需要我们指定创建代理对象/目标对象实现的接口的类型 ...

最新文章

  1. html表格极细边框,html中表格细边框的四种实现及其比较
  2. oracle排序使用,很多中函数,不同的效果
  3. LoadRunner 脚本语言认识
  4. 【问题收集·知识储备】Xcode只能选择My Mac,不能选择模拟器如何解决?
  5. 直播间越播越没人,大部分刚开始做直播电商的人都会这样
  6. 光滑噪声数据常用的方法_数据挖掘部分课后习题
  7. 数据结构(java语言描述)课后答案_数据结构JAVA语言描述习题答案(刘小晶等主编)pdf总复习.ppt...
  8. CSS修改input标签中placeholder值的文字样式
  9. 远程桌面由于以下原因无法连接远程计算机,win10远程桌面提示由于以下原因之一无法连接的解决教程...
  10. 基于matlab的车牌定位算法设计与实现,原创】基于matlab的汽车牌照识别系统设计与实现...
  11. Android如何让Fragment加载到Activity中
  12. AStar 拐点 算法实现AI寻路
  13. Angular 基础
  14. 梅赛德斯-奔驰将区块链技术应用于可持续交易账簿及供应链
  15. 安装完anaconda怎么创建新的虚拟环境
  16. java项目-第34期基于SpringBoot实现的中小医院HIS管理系统【毕业设计】
  17. 小青蛙oracle跟踪,在小青蛙TOAD中用oracle语句写
  18. Spring定时器之翘楚-Quartz
  19. 手撕TreeMap红黑树
  20. linux显示桌面命令,linux显示桌面快捷键设置

热门文章

  1. Grafana 未经授权任意访问漏洞(CVE-2022-32275)
  2. (无报错)Java截取视频生成Gif动图 视频转gif动态图 视频截帧取图 java实现方式
  3. Python 3中的lambda函数使用
  4. java 圆角组件_Java圆角和透明的边框
  5. 中柏pad7安装linux,接个键盘就是电脑 中柏EZpad 7改变移动办公体验
  6. android 自定义view仿支付宝写五褔及播放
  7. 【Android游戏开发十二】(保存游戏数据 [上文])详解SharedPreference 与 FIleInputStream/FileOutputStream将数据存储到SD卡中!
  8. spring web 知识点过一遍
  9. php为什么没有npm,在phpstorm的terminal中输入npm显示不是内部或外部命令
  10. 设备树 之pinctrl[通俗易懂]