Spring事务管理概述
文章目录
简单记录 - 简单记录-Java EE企业级应用开发教程(Spring+Spring MVC+MyBatis) 和 Spring 3.0就这么简单 -Spring的事务管理
Spring提供了灵活方便的事务管理功能,但这些功能都是基于底层数据库本身的事务处理机制工作的。
要想深入了解Spring的事务管理和配置,就非常有必要先学习数据库事务的基础知识。
数据库事务
那什么是数据库事务呢?
先了解下事务思想吧。
事务的思想:
很多复杂的事物要分步进行(复杂的东西经常拆分),但它们组成一个整体,要么整体生效,要么整体失效。这种思想反映到数据库上,就是多个SQL语句,要么所有执行成功,要么所有执行失败。
数据库事务:
数据库事务(Database Transaction)是指将一系列数据库操作当作一个逻辑处理单元的操作,**这个单元中的数据库操作要么完全执行,要么完全不执行。**通过将一组相关操作组合为一个逻辑处理单元,可以简化 错误恢复,并使应用程序更加可靠。
一个逻辑处理单元要成为事务,必须满足ACID属性。(原子性Atomic、一致性Consistency、隔离性Isolation和持久性Durabiliy),所谓的ACID含义如下。
- 原子性(Atomicity):表示组成一个事务的多个数据库操作是一个不可分割的原子单元,只有所有的操作执行成功,整个事务才提交,事务中任何一个数据库操作失败,已经执行的任何操作都必须撤销,让数据库返回到初始状态。也就是一个事务内的操作,要么全部执行成功,要么全部执行不成功。
- 一致性(Consistency):事务执行后,数据库所处的状态和它的业务规则是一致的,即数据不会被破坏。如转账业务,无论事务执行成功与否,参与转账的两个账号余额之和应该是不变的(两人的钱总额是不变的。)。
- 隔离性(Isolation):在并发数据操作时,不同的事务拥有各自的数据空间,它们的操作不会对对方产生干扰。准确地说,并非要求做到完全无干扰,数据库规定了多种事务隔离级别,不同隔离级别对应不同的干扰程度,**隔离级别越高,数据一致性越好,但并发性越弱。**每个事务独立运行。在并发环境中,并发的事务是互相隔离的,互不影响。
- 持久性(Durability):一旦事务提交成功后,事务中所有的数据操作都必须被持久化到数据库中,即使提交事务后,数据库马上崩溃,在数据库重启时,也必须保证能够通过某种机制恢复数据。也就是事务一旦提交后,数据库中的数据必须被永久地保存下来。
在这些事务特性中,数据“一致性”是最终目标,其他的特性都是达到这个目标的措施、要求或手段。
数据库管理系统一般采用重执行日志保证原子性、一致性和持久性,重执行日志记录了数据库变化的每一个动作,数据库在一个事务中执行一部分操作后发生错误退出,数据库即可以根据重执行日志撤销已经执行的操作。此外,对于已经提交的事务,即使数据库崩溃,在重启数据库时也能够根据日志对尚未持久化的数据进行相应的重执行操作。
和Java程序采用对象锁机制进行线程同步类似,数据库管理系统采用数据库锁机制保证事务的隔离性。当多个事务试图对相同的数据进行操作时,只有持有锁的事务才能操作数据,直到前一个事务完成后,后面的事务才有机会对数据进行操作。Oracle数据库还使用了数据版本的机制,在回滚段为数据的每个变化都保存一个版本,使数据的更改不影响数据的读取。
什么是Spring的事务管理?
那什么是Spring的事务管理?
在实际开发中,操作数据库时都会涉及到事务管理问题,为此Spring提供了专门用于事务处理的API。Spring的事务管理简化了传统的事务管理流程,并且在一定程度上减少了开发者的工作量。具体来说就是Spring提供的事务管理,使开发人员在做数据库操作时,无须再手动执行对数据库的提交或回滚操作,并且Spring还提供了对事务传播的支持,可以实现更加复杂的事务嵌套的逻辑,对数据一致性提供了更好的支持。
Spring事务管理
Spring对事务管理的支持
Spring对事务管理的支持
Spring为事务管理提供了一致的编程模板,在高层次建立了统一的事务抽象。也就是说,不管选择Spring JDBC、Hibernate、JPA,还是MyBatis,Spring都让用户可以用统一的编程模型进行事务管理。
像Spring DAO为不同的持久化实现提供了模板类一样,Spring事务管理继承了这一风格,也提供了事务模板类TransactionTemplate。通过事务模板类TransactionTemplate并配合使用事务回调TransactionCallback指定具体的持久化操作就可以通过编程方式实现事务管理,而无须关注资源获取、复用、释放、事务同步和异常处理的操作。
Spring事务管理的亮点在于声明式事务管理。Spring允许通过声明方式,在IoC配置中指定事务的边界和事务属性,Spring自动在指定的事务边界上应用事务属性。声明式事务是EJB赫一时的技术,Spring让这种技术平民化,甚至可以说,Spring的声明事务比EJB的更为强大。
EJB事务建立在JTA的基础上,而JTA又必须通过JNDI获取,这意味着,不管用户的应用是跨数据源的应用,还是单数据源的应用,EJB都要求使用全局事务的方式加以处理,这意味着基于EJB的应用无法脱离应用服务器所提供的容器环境。这种不加区分一概而论的做法无异于杀鸡杀牛都用一把宰牛刀。
Spring深刻地认识到:大部分应用都基于单数据源,只有为数不多的应用需要使用到多数据源的JTA事务。因此,在单数据源的情况下,Spring直接使用底层的数据源管理事务。在面对多数据源的应用时,Spring才寻求Java EE应用服务器的支持,通过引用应用服务器中的JNDI资源完成JTA事务。Spring让人印象深刻的地方在于不管用户使用何种持久化实现技术,也不管用户是否使用了JTA事务,都可以采用相同事务管理模型。
这种统一的处理方式所带来的好处是不可估量的:用户完全可以抛开事务管理的问题编写程序,并在Spring中通过配置完成事务的管理工作。
Spring事务管理的核心接口
在Spring的所有JAR包中,包含一个名为spring-tx-5.2.3.RELEASE的JAR包,该包就是Spring提供的用于事务管理的依赖包。在该JAR包的org.springframework.transaction包中,有3个接口文件PlatformTransactionManager、TransactionDefinition和TransactionStatus
Spring事务管理的三个核心接口
1.PlatformTransactionManager
2.TransactionDefinition
3.TransactionStatus
TransactionDefinition用于描述事务的隔离级别、超时时间、是否为只读事务和事务传播规则等控制事务具体行为的事务属性,这些事务属性可以通过XML配置或注解描述提供,也可以通过手工编程的方式设置。PlatformTransactionManager根据TransactionDefinition提供的事务属性配置信息,创建事务,并用TransactionStatus描述这个激活事务的状态。下面分别介绍这些SPI(Service Provider Interface)接口内部的组成。
https://docs.spring.io/spring/docs/current/javadoc-api/
Platform TransactionManager
PlatformTransactionManager接口是Spring提供的平台事务管理器,主要用于管理事务。该接口中提供了三个事务操作的方法,具体如下:
TransactionStatus getTransaction(TransactionDefinition definition);
该方法根据事务定义信息从事务环境中返回一个已存在的事务,或者创建一个新的事务,并用TransactionStatus描述这个事务的状态。(用于获取事务状态信息)
void commit(TransactionStatus status);
根据事务的状态提交事务,如果事务状态已经被标识为rollback-only,该方法将执行一个回滚事务的操作。(用于提交事务)
void rollback(TransactionStatus status);将事务回滚。当commit()方法抛出异常时,rollback()会被隐式调用。(用于回滚事务)
在上面的3个方法中,getTransaction(TransactionDefinition definition)方法会根据TransactionDefinition参数返回一个TransactionStatus对象,TransactionStatus对象就表示一个事务,它被关联在当前执行的线程上。
PlatformTransactionManager接口只是代表事务管理的接口,并不知道底层是如何管理事务的,具体如何管理事务则由它的实现类来完成。该接口常见的几个实现类如下:
常用接口实现类
org.springframework.jdbc.datasource.DataSourceTransactionManager
用于配置JDBC数据源的事务管理器
org.springframework.orm.hibernate4.HibernateTransactionManager
用于配置Hibernate的事务管理器
org.springframework.transaction.jta.JtaTransactionManager
用于配置全局事务管理器
提示:当底层采用不同的持久层技术时,系统只需使用不同的PlatformTransactionManager实现类即可。
TransactionDefinition
TransactionDefinition接口是事务定义(描述)的对象,该对象中定义了事务规则,并提供了获取事务相关信息的方法,具体如下:
String getName( ); 获取事务对象名称
int getIsolationLevel( ); 获取事务的隔离级别
int getPropagationBehavior( ); 获取事务的传播行为
int getTimeout( ); 获取事务的超时时间
boolean isReadOnly( ); 获取事务是否只读
上述方法中,事务的传播行为是指在同一个方法中,不同操作前后所使用的事务。传播行为有很多种,具体如下表所示:
在事务管理过程中,传播行为可以控制是否需要创建事务以及如何创建事务,通常情况下,数据的查询不会影响原数据的改变,所以不需要进行事务管理,而对于数据的插入、更新和删除操作,必须进行事务管理。如果没有指定事务的传播行为,Spring默认传播行为是REQUIRED。
TransactionStatus
TransactionStatus接口是事务的状态,它描述了某一时间点上事务的状态信息。事务管理器通过该接口获取事务运行期的状态信息,也可以通过该接口间接地回滚事务,它相比于在抛出异常时回滚事务的方式更具可控性。该接口继承于SavepointManager接口,SavepointManager接口基于JDBC 3.0保存点的分段事务控制能力提供了嵌套事务的机制。
该接口中包含6个方法,具体如下。
void flush(); 刷新事务
boolean hasSavepoint(); 获取是否存在保存点
boolean isCompleted(); 获取事务是否完成
boolean isNewTransaction(); 获取是否为新事务,如果返回false,表示当前事务是一个已经存在的事务,或者当前操作未运行在事务环境中。
boolean isRollbackOnly(); 获取事务是否回滚
void setRollbackOnly(); 设置事务回滚,将当前的事务设置为rollback-only。通过该标识通知事务管理器只能将事务回滚,事务管理器将通过显式调用回滚命令或抛出异常的方式回滚事务。
事务管理的方式