什么是事务管理?
-
第一个问题:什么是事务?事务一般是相对数据库而言的,对于数据库一次操作就属于一个事务, 一次操作可以是几句 SQL 语句,也可以是若干行 JDBC 的 Java 语句。事务既然那么重要,那么它肯定有不一般的原则把?没错,那就是 ACID 原则。
-
ACID(Atomicity,Consistency,Isolation,Durability)原则
-
A 代表原子性事务中的读和写操作可看作是对数据库的单个原子操作。原子性保证了整个事务中的所有操作,要么全部完成,要么全部不完成,不可能停滞在中间某个环节。这就导致了一次操作对某一数据的修改在事务失败后一定会恢复原来的数据。
-
C 代表一致性一致性保证了事务前后数据的完整性必须保持一致。也就是要符合我们在原子操作中进行的逻辑运算。例如,完整性约束了 a + b = 10,一个事务改变了 a,那么 b 也应该随之改变。
-
I 代表隔离性事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间是相互隔离的。其实可以看做是事务的独立性,即两个以上的事务不会出现交错执行的情况。
-
D 代表持久性持久性保证了某一事务完成以后,该事务对数据库所作的更改便持久的保存在数据库之中,并且不会参与下一次回滚,不会随外界原因而导致数据丢失。我觉得这也是旧数据(那些我们只是查看但未曾操作过的)的特性。
-
总的来说,原子性保证了一个事务的进行是不可分割的;一致性保证了事务一定是正确的;隔离性保证了事务管理是可以对事务进行并发控制的;持久性保证了事务完成后,新数据跟旧数据是可以“一视同仁”的。
-
-
第二个问题:什么是事务管理?假设事务是相对于数据库而言,那么事务管理就是对于一系列数据库操作进行管理。其实事务管理很普遍,就比如说你跟别人转账,突然断网了,这个时候转账就会出错。在没有事务管理的情况下,可能你的钱就会不翼而飞了,而且别人也没有收到。
-
第三个问题:什么是 Spring 的事务管理?在实际开发中,操作数据库时都会涉及到事务管理问题,为此 Spring 提供了专门用于事务处理的 API。Spring 的事务管理简化了传统的事务管理流程,并且在一定程度上减少了开发者的工作量。
须知
-
由于声明式事务管理涉及到面向切面编程,所以需要事先导入如下 Jar 包:
-
aopalliance-1.0.jar
-
aspectjweaver-1.8.0.jar
-
spring-aop-4.3.6.RELEASE.jar
-
事务管理的三个核心接口
-
核心接口所在的包
-
在 Spring 的所有JAR包中,包含一个名为 spring-tx-4.3.6 RELEASE 的 JAR 包该包就是 Spring 提供的用于事务管理的依赖包。
-
在该 JAR 包的 org.springframework transaction 包中,有 3 个接口文件,它们分别是 Spring 事务管理的三个核心接口。
-
-
第一个接口:PlatformTransactionManager
-
Spring 提供的平台事务管理器,主要用于管理事务,下面是其主要的三个方法:
-
用于获取事务状态信息:TransactionStatus getTransaction( TransactionDefinition definition )
-
用于提交事务(我们见的最多的):void commit( TransactionStatus status )
-
用于回滚事务:void rollback( TransactionStatus status )
-
-
PlatformTransactionManage 的实现类
-
PlatformTransactionManager 接囗只是代表事务管理的接口,并不知道底层是如何管理事务的,具体如何管理事务则由它的实现类来完成。该接口常见的几个实现类如下:
-
当底层采用不同的持久层技术时,系统只需使用不同的 PlatformTransactionManager 实现类即可。
-
-
第二个接口:TransactionDefinition
-
TransactionDefinition 接口是事务定义(描述)的对象,该对象中定义了事务规则,并提供了获取事务相关信息的方法,具体如下:
-
获取事务对象名称:String getName( );
-
获取事务的隔离级别:int getIsolationLevel( );
-
获取事务的传播行为:int getPropagationBehavior( );
-
获取事务的超时时间:int getTimeout( );
-
获取事务是否只读:boolean isReadOnly( );
-
-
第三个接口:TransactionStatus
-
TransactionStatus 接口是事务的状态,它描述了某一时间点上事务的状态信息,该接口中包含 6 个方法,具体如下:
-
刷新事务:void flush( );
-
获取是否存在保存点:boolean hasSavepoint( );
-
获取事务是否完成:boolean isCompletede( );
-
获取是否为新事务:boolean isNewTransaction( );
-
获取事务是否回滚:boolean isRollbackOnly( );
-
设置事务回滚:void setRollbackOnly( );
-
-
示意图
-
事务的传播行为
-
上述方法中,事务的传播行为是指在同一个方法中,不同操作前后所使用的事务。传播行为有很多种,具体如下表所示:
-
在事务管理过程中,传播行为可以控制是否需要创建事务以及如何创建事务。通常情况下,数据的查询不会影响原数据的改变,所以不需要进行事务管理。而对于数据的插入、更新和删除操作,必须进行事务管理。如果没有指定事务的传播行为,Spring 默认传播行为是 REQUIRED。
事务管理的方式(两种)
-
编程式事务管理通过编写代码实现的事务管理,包括定义事务的开始、正常执行后的事务提交和异常时的事务回滚。
-
声明式事务管理通过 AOP 技术实现的事务管理,主要思想是将事务作为一个“切面”代码单独编写,然后通过 AOP 技术将事务管理的“切面”植入到业务目标类中。
-
推荐使用声明式事务管理声明式事务管理最大的优点在于开发者无需通过编程的方式来管理事务,只需在配置文件中进行相关的事务规则声明,就可以将事务应用到业务逻辑中。这使得开发人员可以更加专注于核心业务逻辑代码的编写,在一定程度上减少了工作量,提高了开发效率,所以在实际开发中,通常都推荐使用声明式事务管理。
基于 XML 方式的声明式事务
-
基于 XML 方式的声明式事务是在配置文件中通过 <tx: advice> 元素配置事务规则来实现的。当配置了事务的增强处理后,就可以通过编写的 AOP 配置,让 Spring 自动对目标生成代理。<x: advice>元素及其子元素如下图所示:
-
配置 <tx: advice> 元素的重点是配置 <tx: method> 子元素,上图中使用灰色标注的几个属性是 <tx: method> 元素中的常用属性。其属性描述具体如下:
基于 Annotation 方式的声明式事务
-
大致需要两步
-
在 Spring 容器中注册事务注解驱动:
-
<tx: annotation-driven transaction-manager="transaction Manager"/>
-
-
在需要事务管理的类或方法上使用 @Transactional 注解
-
如果将注解添加在 Bean 类上,则表示事务的设置对整个 Bean 类的所有方法都起作用;
-
如果将注解添加在 Bean 类中的某个方法上,则表示事务的设置只对该方法有效。
-
-
-
其中,使用 @Transactional 注解时,可以通过参数配置事务详情: