Spring事务的一些总结

news/2024/11/23 2:46:05/

文章目录

    • 1 @Transactional 注解特性
    • 2 事务的属性
    • 3 事务的嵌套
    • 4 事务超时设置
    • 5 @Transaction注解不回滚的可能原因
    • 6 事务的基本要素(ACID)
    • 7 事务的原理
    • 8 数据并发问题
    • 9 数据库隔离级别
    • 10 Spring隔离级别
    • 11 底层所使用的不同的持久化API或框架

1 @Transactional 注解特性

  • 可以在整个类上添加@Transactional,会将整个类纳入Spring事务管理,在每个业务方法执行时都会开启一个事务,不过这些事务采用相同的管理方式。
  • @Transactional 注解只能应用到 public 可见度的方法上。如果应用到protected、private可见度的方法上,也不会报错,但是事务不会起作用。
  • 默认情况下,spring会对unchecked异常进行事务回滚;如果是checked异常则不回滚。 即:出现的空指针等异常,会被回滚,文件读写,网络出问题不回滚。

java里面将派生于Error或者RuntimeException(比如空指针,除数为0)的异常称为unchecked异常,
其他继承自java.lang.Exception得异常统称为Checked Exception,如IOException、TimeoutException等

  • 通常情况下,仅是读取数据时,不必设置只读事务而增加额外的系统开销。

2 事务的属性

  • 1、REQUIRED(默认)

业务方法需要在一个容器里运行。如果方法运行时,已经处在一个事务中,那么加入到这个事务,如果没有则新建一个自己的事务。

  • 2、SUPPORTS

该方法在某个事务范围内被调用,则方法称为该事务的一部分。如果方法在该事务范围外被调用,则该方法就在没有事务的环境下执行。

  • 3、MANDATORY

该方法只能在一个已存在的事务中执行,业务方法不能发起自己的事务。如果在没有事务的环境下被调用,容器抛出异常。

  • 4、REQUIRED_NEW

不管是否存在事务,该方法总会为自己发起一个新的事务。如果方法已经运行在一个事务中,则原有事务挂起,新的事务被创建。

  • 5、NOT_SUPPORTED

声明方法不需要事务。如果方法没有关联到一个事务,容器不会为他开启事务,如果方法在一个事务中被调用,则该事务会被挂起,调用结束后,原先的事务会恢复执行。

  • 6、NEVER

该方法绝对不能在事务范围内执行。如果在就抛出异常。只有该方法没有关联到任何事务,才正常执行。

  • 7、NESTED

如果一个活动的事务存在,则运行在一个嵌套的事务中。如果没有活动事务,则按REQUIRED属性执行。它使用了一个单独的事务,这个事务拥有多个可以回滚的保存点。内部事务的回滚不会对外部事务造成影响。它只对DataSourceTransactionManager事务管理器起效。

3 事务的嵌套

  • 如果使用@Transaction方法里嵌套调用的是同一个类的方法,spring代理会忽略嵌套方法的@Transaction配置。如果是其他注入对象的方法,那么@Transaction配置就会生效。
  • 调用方法是REQUIRED(默认),被调用方法是NERVER,则会抛出异常,事务不会生效,也不会回滚,数据库中的数据已被修改。
  • 调用方法是NEVER,被调用方法是REQUIRED,会抛出异常。因为:++NERVER 不允许当前存在事务++
  • REQUIRED子事务会影响当前事务的提交、回滚,具体体现在,一个方法中调用其他对象的方法,如果失败了,会导致整个方法回滚。
  • NESTED子事务回滚不会影响当前事务的提交(catch回滚异常的情况下),但是当前事务回滚会回滚子事务。也就是说只有当前事务提交成功了,子事务才会提交成功。
  • NESTED(嵌套事务)和REQUIRED_NEW(新的事务):假设都是在一个REQUIRED类型的事务里调用这些事务,该REQUIRED类型方法调用抛出异常,REQUIRED_NEW的方法仍然可以提交,但是NESTED还要受到REQUIRED事务回滚而被迫回滚。
  • REQUIRES_NEW会启用一个新的事务,事务拥有完全独立的能力,它不依赖于当前事务,执行时会挂起当前事务,直到REQUIRES_NEW事务完成提交后才会提交当前事务,如果当前事务与REQUIRES_NEW 存在锁竞争,会导致死锁。
  • NOT_SUPPORTED会挂起当前事务,并且NOT_SUPPORTED定义的方法内部不启用显示事务,如果NOT_SUPPORTED和当前事务存在锁竞争,会发生死锁。
  • MANDATORY必须包含在事务中,如果事务不存在,则抛出异常。

4 事务超时设置

@Transactional(timeout=30) //默认是30秒

5 @Transaction注解不回滚的可能原因

  • 检查方法是不是public的
  • 检查异常类型是不是unchecked异常

如果想要check异常也回滚,在注解上写明异常类型即可:@Transactional(rollbackFor=Exception.class),类似的还有norollbackFor,自定义不回滚的异常。

  • 数据库引擎要支持事务,如果是mysql,注意表要使用支持事务的引擎,比如innodb,如果是myisam,事务是不起作用的。
  • 检查是否开启了对注解的解析
  • 查看spring是否扫描到了这个包

6 事务的基本要素(ACID)

  • 原子性(Atomicity):指一个事务的全部操作是一个整体,要么执行成功,要么执行失败。
  • 一致性(Consistency):在事务执行前和执行完成后,数据完整性约束没有被破坏,完全符合所有预期。
  • 隔离性(Isolation):数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读已提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。
  • 持久性(Durability):事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

7 事务的原理

  • 纯JDBC操作
  • 先获取连接 Connection conn = DriverManager.getConnection()
  • 开启事务 conn.setAutoCommit(true)
  • 执行相关的SQL语句
  • 提交或者回滚事务 conn.commit() conn.rollback()
  • 关闭连接
  • Spring事务管理
  • 在相关的类或者方法上通过注解@Transactional标识。
  • Spring在启动时回去解析生成相关的bean,这时候会查看拥有相关注解的类和方法,并且为这些类和方法生成代理,并根据@Transactional的相关参数进行相关配置注入,通过代理的方式处理开启、提交、回滚事务。
  • 真正的数据库层的事务提交和回滚是通过binlog或者redo log实现的。

8 数据并发问题

  • 脏读

事务T1正在操作一条数据,此时事务T2获取该条数据纪录,如果T1异常,事务回滚,T2读取到的数据就是脏数据,这种现象称为脏读。

  • 不可重复读

事务T1多次读取某条记录,在读取间隔中,事务T2更新了该记录的数据,当T1再次读取该记录时,获取到的数据不一致,这种现象称为不可重复读。产生的原因主要是数据的更新,解决不可重复读只需要锁住满足条件的行

  • 幻读

事务T1批量处理多条记录,此时事务T2新增或删除了一条或多条记录,当T1处理完成,查询处理结果,会发现有记录没有处理(T2新增的)或者发现记录少了(T2删除的),会有一种幻觉的感觉,这种现象称为幻读。主要是数据的新增或删除导致,解决幻读需要锁表

9 数据库隔离级别

隔离级别隔离级别的值脏读不可重复读幻读
读未提交 Read-Uncommitted0
读提交 Read-Committed1
可重复读 Repeatable-Read2
序列化 Serializable3
  • 读未提交(Read-Uncommitted)
  • 定义:就是一个事务读取到其他事务未提交的数据,是级别最低的隔离机制。
  • 缺点:会产生脏读、不可重复读、幻读。
  • 读提交(Read-Committed)
  • 定义:就是一个事务读取到其他事务提交后的数据。SqlServer、Oracle默认隔离级别
  • 缺点:会产生不可重复读、幻读。
  • 可重复读(Repeatable-Read)
  • 定义:就是一个事务对同一份数据读取到的相同,不在乎其他事务对数据的修改。MySQL默认的隔离级别
  • 缺点:会产生幻读。
  • 序列化(Serializable)
  • 定义:事务串行化执行,隔离级别最高,牺牲了系统的并发性。
  • 缺点:可以解决并发事务的所有问题。但是效率地下,消耗数据库性能,一般不使用。

10 Spring隔离级别

  • ISOLATION_DEFAULT

PlatfromTransactionManager 默认的隔离级别,使用数据库默认的事务隔离级别。

  • ISOLATION_READ_UNCOMMITTED(读未提交)

同数据库的Read-Committed

  • ISOLATION_READ_COMMITTED(读提交)

同数据库的Read-Committed

  • ISOLATION_REPEATABLE_READ(可重复读)

同数据库的Repeatable-Read

  • ISOLATION_SERIALIZABLE(序列化)

同数据库的Serializable

11 底层所使用的不同的持久化API或框架

  • DataSourceTransactionManager

适用于使用JDBC和iBatis进行数据持久化操作的情况,在定义时需要提供底层的数据源作为其属性,也就是 DataSource

  • HibernateTransactionManager

适用于使用Hibernate进行数据持久化操作的情况,与 HibernateTransactionManager 对应的是 SessionFactory

  • JpaTransactionManager

适用于使用JPA进行数据持久化操作的情况,与 JpaTransactionManager 对应的是 EntityManagerFactory。


http://www.ppmy.cn/news/768906.html

相关文章

计算机科学与技术万金油专业,盘点工学大类里的“万金油”专业

原标题:盘点工学大类里的“万金油”专业 教育部2012年最新修订的本科生专业名录中把专业重新进行了从学科门类到专业类和专业的划分,共计12大学科门类,分别是理、工、农、医 ,管、教、文、艺 经、史、法、哲.92大专业类&#xff0…

程序员的浪漫(使用python画图)比心心(待完善版)

本人给女朋友准备的小惊喜,如有需要可以取用。(代码内有注释可根据需要更改) #比心!! import turtle # turtle.bgpic(D:/python/bjtp/aa.jpg) turtle.speed(10)#画笔速度 turtle.setup(1800,700,70,70) turtle.color(b…

一行代码解决判断IE浏览器和提示升级问题

IE8及以下版本提示升级&#xff08;使用IE9和旧版IE支持 if IE 条件注释语句实现&#xff09; <!--[if lte IE 8]><script>alert("您正在使用的浏览器版本过低&#xff0c;为了您的最佳体验&#xff0c;请先升级浏览器。");window.location.href"h…

win7 ie11版本安装报此更新不适用于计算机问题

IE版本升级需要KB2729094、KB2731771、KB2533623、KB2670838、KB2786081五个补丁安装 五个补丁需要根据计算机决定并下载&#xff0c;如&#xff1a;32位选x86 64位选X64 补丁安装时如果也出现了此更新不适用于计算机问题&#xff0c;可以在dos&#xff08;管理员身份&#xf…

浏览器为低版本IE的时候的信息提示;旧版 Internet Explorer 升级提示页;旧版 Internet Explorer 淘汰行动

本部分内容来自&#xff1a;https://support.dmeng.net/ 旧版 Internet Explorer 升级提示页 旧版 Internet Explorer 淘汰行动 微软对旧版 Internet Explorer 的支持服务已终止的说明 X-UA-Compatibility Meta Tag and HTTP Response Header if IE 条件注释说明 360浏览…

IE低版本常见的兼容问题解决

当每次谈到解决低版本IE兼容问题时&#xff0c;不知道大家有没有一种头皮发麻的感觉(内心独白&#xff1a;谁tm发明的IE&#xff0c;我要s了他&#xff0c;开个玩笑&#xff09;. 下面我们就简单谈一谈低版本IE常见的兼容问题&#xff1a; 在我们解决浏览器的兼容问题时&…

h5前端IE浏览器低版本判断及升级提示

需求&#xff1a; 由于公司项目对于ie浏览器只支持ie10及以上版本&#xff0c;为了更好的用户体验及人性化提示&#xff0c;想在代码里判断下ie浏览器低版本加个提示。 解决方案&#xff1a; 先贴代码&#xff1a; <!--[if lte IE 9]><script>alert("您正…

IE浏览器低版本判断及升级提示

需求&#xff1a; 由于公司项目对于ie浏览器只支持ie10及以上版本&#xff0c;为了更好的用户体验及人性化提示&#xff0c;想在代码里判断下ie浏览器低版本加个提示。 解决方案&#xff1a; 先贴代码&#xff1a; <!--[if lte IE 9]><script>alert("您正在使…