Spring 事务管理详细介绍
什么是事务
数据库事务是被视为单个工作单元的一系列操作。 这些操作要么完全完成,要么完全不生效。 事务管理是面向RDBMS的企业应用程序的重要组成部分,用于保证数据的完整性和一致性。 事务的概念可以用以下四个关键属性描述为 ACID
- 原子性 - 事务应被视为单个操作单元,这意味着整个操作序列成功或不成功。
- 一致性 - 这表示数据库的引用完整性、表中的唯一主键等的一致性。
- 隔离性 - 同时可能有许多具有相同数据集的事务处理。 每个事务都应与其他事务隔离,以防止数据损坏。
- 持久性 - 一旦事务完成,该事务的结果必须永久保存,并且由于系统故障而不能从数据库中删除。
一个真正的 RDBMS 数据库系统将保证每个事务的所有四个属性。 使用 SQL 向数据库发出事务的简单视图如下
- 使用开始事务命令开始事务。
- 使用 SQL 查询执行各种删除、更新或插入操作。
- 如果所有操作都成功,则执行提交,否则回滚所有操作
Spring 框架在不同的底层事务管理 API 之上提供了一个抽象层。 Spring 的事务支持旨在通过向 POJO 添加事务功能来提供 EJB 事务的替代方案。 Spring 支持编程式和声明式事务管理。 EJB 需要一个应用服务器,但是 Spring 事务管理可以在不需要应用服务器的情况下实现。
局部与全局事务
本地事务特定于单个事务资源,如 JDBC 连接,而全局事务可以跨越多个事务资源,如分布式系统中的事务。
本地事务管理在应用程序组件和资源位于单个站点的集中式计算环境中非常有用,并且事务管理仅涉及在单个机器上运行的本地数据管理器。 本地事务更容易实现。
在所有资源都分布在多个系统中的分布式计算环境中,需要全局事务管理。 在这种情况下,事务管理需要在本地和全局级别进行。 分布式或全局事务跨多个系统执行,其执行需要全局事务管理系统和所有相关系统的所有本地数据管理器之间的协调。
程序式 与 声明式
Spring 支持两种类型的事务管理 -
- 程序式事务管理 - 这意味着您必须在编程的帮助下管理事务。 这为您提供了极大的灵活性,但很难维护。
- 声明式事务管理 - 这意味着您将事务管理与业务代码分开。 只使用注释或基于 XML 的配置来管理事务。
声明式事务管理优于程序式事务管理,尽管它不如程序式事务管理灵活,后者允许我们通过代码控制事务。 但是作为一种横切关注点,声明式事务管理可以使用 AOP 方法进行模块化。 Spring 通过 Spring AOP 框架支持声明式事务管理。
Spring 事务抽象
Spring事务抽象的关键由org.springframework.transaction.PlatformTransactionManager接口定义,如下
public interface PlatformTransactionManager {
TransactionStatus getTransaction(TransactionDefinition definition);
throws TransactionException;
void commit(TransactionStatus status) throws TransactionException;
void rollback(TransactionStatus status) throws TransactionException;
}
序号 | 方法 | 描述 |
---|---|---|
1 | TransactionStatus getTransaction(TransactionDefinition definition) | 根据指定的传播行为,该方法返回当前活动事务或创建一个新的事务。 |
2 | void commit(TransactionStatus status) | 该方法提交给定的事务和关于它的状态。 |
3 | void rollback(TransactionStatus status) | 该方法执行一个给定事务的回滚。 |
TransactionDefinition 是 Spring 中事务支持的核心接口,定义如下
public interface TransactionDefinition {
int getPropagationBehavior();
int getIsolationLevel();
String getName();
int getTimeout();
boolean isReadOnly();
}
序号 | 方法 | 描述 |
---|---|---|
1 | int getPropagationBehavior() | 该方法返回传播行为。Spring 提供了与 EJB CMT 类似的所有的事务传播选项。 |
2 | int getIsolationLevel() | 该方法返回该事务独立于其他事务的工作的程度。 |
3 | String getName() | 该方法返回该事务的名称。 |
4 | int getTimeout() | 该方法返回以秒为单位的时间间隔,事务必须在该时间间隔内完成。 |
5 | boolean isReadOnly() | 该方法返回该事务是否是只读的。 |
以下是隔离级别的可能值
序号 | 隔离级别 | 描述 |
---|---|---|
1 | TransactionDefinition.ISOLATION_DEFAULT | 这是默认的隔离级别。 |
2 | TransactionDefinition.ISOLATION_READ_COMMITTED | 表明能够阻止误读;可以发生不可重复读和虚读。 |
3 | TransactionDefinition.ISOLATION_READ_UNCOMMITTED | 表明可以发生误读、不可重复读和虚读。 |
4 | TransactionDefinition.ISOLATION_REPEATABLE_READ | 表明能够阻止误读和不可重复读;可以发生虚读。 |
5 | TransactionDefinition.ISOLATION_SERIALIZABLE | 表明能够阻止误读、不可重复读和虚读。 |
以下是传播类型的可能值
序号 | 传播类型 | 描述 |
---|---|---|
1 | TransactionDefinition.PROPAGATION_MANDATORY | 支持当前事务;如果不存在当前事务,则抛出一个异常。 |
2 | TransactionDefinition.PROPAGATION_NESTED | 如果存在当前事务,则在一个嵌套的事务中执行。 |
3 | TransactionDefinition.PROPAGATION_NEVER | 不支持当前事务;如果存在当前事务,则抛出一个异常。 |
4 | TransactionDefinition.PROPAGATION_NOT_SUPPORTED | 不支持当前事务;而总是执行非事务性。 |
5 | TransactionDefinition.PROPAGATION_REQUIRED | 支持当前事务;如果不存在事务,则创建一个新的事务。 |
6 | TransactionDefinition.PROPAGATION_REQUIRES_NEW | 创建一个新事务,如果存在一个事务,则把当前事务挂起。 |
7 | TransactionDefinition.PROPAGATION_SUPPORTS | 支持当前事务;如果不存在,则执行非事务性。 |
8 | TransactionDefinition.TIMEOUT_DEFAULT | 使用默认超时的底层事务系统,或者如果不支持超时则没有。 |
TransactionStatus 接口为事务代码提供了一种简单的方式来控制事务执行和查询事务状态。
public interface TransactionStatus extends SavepointManager {
boolean isNewTransaction();
boolean hasSavepoint();
void setRollbackOnly();
boolean isRollbackOnly();
boolean isCompleted();
}
序号 | 方法 | 描述 |
---|---|---|
1 | boolean hasSavepoint() | 该方法返回该事务内部是否有一个保存点,也就是说,基于一个保存点已经创建了嵌套事务。 |
2 | boolean isCompleted() | 该方法返回该事务是否完成,也就是说,它是否已经提交或回滚。 |
3 | boolean isNewTransaction() | 在当前事务时新的情况下,该方法返回 true。 |
4 | boolean isRollbackOnly() | 该方法返回该事务是否已标记为 rollback-only。 |
5 | void setRollbackOnly() | 该方法设置该事务为 rollback-only 标记。 |