Spring - 事务管理
数据库事务是被视为单个工作单元的一系列操作。 这些操作要么完全完成,要么完全不生效。 事务管理是面向RDBMS的企业应用程序的重要组成部分,用于保证数据的完整性和一致性。 事务的概念可以用以下四个关键属性描述为 ACID −
原子性 − 事务应被视为单个操作单元,这意味着整个操作序列要么成功,要么不成功。
一致性 − 这代表了数据库的引用完整性、表中唯一主键等的一致性。
隔离性 − 一个事务的执行不能其它事务干扰。即一个事务内部的操作及使用的数据对其它并发事务是隔离的,并发执行的各个事务之间不能互相干扰。
持续性 − 也称永久性,指一个事务一旦提交,它对数据库中的数据的改变就应该是永久性的。接下来的其它操作或故障不应该对其执行结果有任何影响。
一个真正的 RDBMS 数据库系统将保证每个事务的所有四个属性。 使用 SQL 向数据库发出事务的简单视图如下 −
使用 begin transaction 命令开始事务。
使用 SQL 查询执行各种删除、更新或插入操作。
如果所有操作都成功则执行 commit提交,否则 rollback 回滚所有操作。
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() 此方法返回事务是否已被标记为仅回滚。 |
5 |
void setRollbackOnly() 此方法将事务设置为仅回滚。 |