Spring事务机制

1 概述

        Spring事务 的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring是无法提供事务功能的。以JDBC为例,其通过事务操作数据库记录步骤如下:

  1. 获取连接:Connection con = DriverManager.getConnection();
  2. 开启事务:con.setAutoCommit(false);
  3. 执行SQL:CRUD等;
  4. 提交事务/回滚事务:con.commit() / con.rollback();
  5. 关闭连接:conn.close();

        spring框架本身依赖的还是这些底层提供的能力,只不过spring对这一过程进行了抽象和封装,使开发者不不必使用这么复杂而原始的方式去操作数据库事务。其他经常使用的数据访问技术(如JPA、mybatis,hibernate等)都有事务处理机制,他们也提供了用来开启事务、提交/回滚事务的相关API。当前所有的数据访问技术都能够很友好的和Spring进行集成,Spring统一处理不同数据访问技术的事务处理。在Spring中提供了一个叫做PlatformTransactionManager接口(相当于spring提供了一套事务操作的规范,不同的数据库访问技术进行实现),不同的数据访问技术都会对该接口进行实现,如表所示:

数据库访问技术JDBCJPAHibernate
实现类DataSourceTransactionManagerJpaTransactionManagerHibernateTransactionManager

2 spring事务的传播特性定义

当多个事务同时存在时,spring应对策略。spring的传播特性如下:

传播特性解释
PROPAGATION_REQUIRED
支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择,也是 Spring 默认的事务的传播。
PROPAGATION_SUPPORTS
支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY
支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW
新建事务,如果当前存在事务,把当前事务挂起。新建的事务将和被挂起的事务没有任何关系,是两个独立的事务,外层事务失败回滚之后,不能回滚内层事务执行的结果,内层事务失败抛出异常,外层事务捕获,也可以不处理回滚操作
PROPAGATION_NOT_SUPPORTED
以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER
以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED
如果一个活动的事务存在,则运行在一个嵌套的事务中。如果没有活动事务,则按REQUIRED属性执行。它使用了一个单独的事务,这个事务拥有多个可以回滚的保存点。内部事务的回滚不会对外部事务造成影响。它只对DataSourceTransactionManager事务管理器起效。

3 数据库事务隔离级别&spring事务隔离级别

数据库事务隔离级别
隔离级别描述
读未提交(Read-Uncommitted)会存在脏读,会读到其他事务未提交的数据,如果其他数据最终回滚,则读到的数据是脏数据。
读已提交(Read-Committed)

避免了脏读,存在不可重复读和幻读。

1. 不可重复读:如果在一个事务中有两次或多次多操作,在这些读取操作之间,另一个事务对数据进行了修改,这时候读取的数据是不一致的。

2. 幻读:一个事务对一定范围的数据进行批量修改,另一个事务在这个范围增加一条数据,此时该事务就会丢失对新增数据的修改。

可重复读(Repeatable-Read)避免了脏读、不可重复读,但是存在幻读
序列化(Serializable)串行化读,事务只能一个一个执行,避免了脏读、不可重复读、幻读。执行效率慢,使用时慎重

spring事务隔离级别在数据库隔离级别基础上新增了一个默认隔离级别,这个级别跟数据库的默认隔离级别保持一致,其余的隔离级别跟数据库隔离级别保一致。

4 spring的两种事务管理

4.1 编程式事务管理

        spring 实现编程式事务主要依赖两个类:PlatformTransactionManager和TransactionTemplate,官方推荐使用TransactionTemplate。

4.2 声明式事务管理

        声明式事务实现方式主要有2种,一种为通过使用Spring的<tx:advice>定义事务通知与AOP相关配置实现,另为一种通过@Transactional实现事务管理实现。spring声明式事务实现是通过AOP来实现的。

使用@Transactional注意点:
        如果在接口、实现类或方法上都指定了@Transactional 注解,则优先级顺序为方法>实现类>接口。
        建议只在实现类或实现类的方法上使用@Transactional,而不要在接口上使用,这是因为如果使用JDK代理机制(基于接口的代理)是没问题;而使用使用CGLIB代理(继承)机制时就会遇到问题,因为其使用基于类的代理而不是接口,这是因为接口上的@Transactional注解是“不能继承的”。

        

参考资料:

https://baijiahao.baidu.com/s?id=1665817944004197918&wfr=spider&for=pc

https://baijiahao.baidu.com/s?id=1677407386011788448&wfr=spider&for=pc

https://www.cnblogs.com/wangyayun/p/6530189.html

https://blog.csdn.net/weixin_44366439/article/details/89030080 源码分析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值