上一章节讲解了数据库的基本事务知识,这些知识是学习Spring事务管理的基础。下面讲解Spring是如何管理事务的。
背景
Spring为事务管理提供了一致的编程模板,在高层次简历了统一的事务抽象。其意思就是,当我们使用SpringJDBC,Hibernate、JPA还是iBatis这些框架时,Spring都让我们可以用统一的编程模型进行事务管理。
Spring事务管理的关键抽象
在Spring事务管理的高层抽象接口主要包括3个接口,分别是PlatformTransactionManager
,TransactionDefinition
和TransactionStatus
,都在org.springframework.transaction
包中。三者关系如下:
TransactionDefinition
TransactionDefinition用于描述事务的隔离级别,超时时间,是否为只读事务和事务传播规则等控制事务具体行为的事务属性,这些事务属性可以通过XML配置或注解描述提供,也可以手工编程设置。
TransactionDefinition定义了Spring兼容的事务属性,这些属性对事务管理控制的若干方面进行配置。
spring可以通过XML和注解元数据方式为一个有事务要求的服务类方法配置事务属性,这些信息作为Spring事务管理框架的“输入”,然后spring会按照配置的事务属性信息,为目标方法提供相应的事务支持。
- 事务隔离:
当前事务和其他事务的隔离程度。在TransactionDefinition接口中,定义了和java.sql.Connection
接口中同名的4个隔离级别,如下1
2
3
4
5
6
7
8
9int ISOLATION_DEFAULT = -1;//默认的隔离级别
int ISOLATION_READ_UNCOMMITTED = Connection.TRANSACTION_READ_UNCOMMITTED;
int ISOLATION_READ_COMMITTED = Connection.TRANSACTION_READ_COMMITTED;
int ISOLATION_REPEATABLE_READ = Connection.TRANSACTION_REPEATABLE_READ;
int ISOLATION_SERIALIZABLE = Connection.TRANSACTION_SERIALIZABLE;
上面的Connection类就是java.sql.Connection
接口,可以看到spring对隔离级别的常量定义就是起了个别名。上面的隔离级别可以参考Spring事务管理详解-事务基础中说明的隔离级别定义。
需要说明的是TransactionDefinition定义的默认的隔离级别,ISOLATION_DEFAULT,它表示使用底层数据库的默认隔离级别。
- 事务传播:
通常在一个事务中执行的所有代码都会运行于同一事务上下文中。但Spring也提供了几个可选的事务传播类型,就是在调用新方法时是否保持和当前方法同一个事务或者新开启事务或挂起当前事务等
当我们调用一个机遇Spring的service接口方法时,它将运行于spring管理的事务环境中,service接口方法可能会在内部调用其他的service接口方法来完成同一个业务完整操作,因此就会产生服务接口方法嵌套调用的情况,spring通过事务创博行为控制当前的事务如何传播到被嵌套调用的目标服务接口方法中。
spring在TransactionDefinition接口总规定了7种事务传播行为,规定事务方法和事务方法发生嵌套调用时,事务如何进行传播,如下:
PROPAGATION_REQUIRED–支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
PROPAGATION_SUPPORTS–支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY–支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW–新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED–以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER–以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED–如果当前存在事务,则在嵌套事务内运行。如果没有事务,则只需与PROPAGATION_REQUIRE类似操作。使用此传播行为时,底层的数据源必须基于JDBC3.0,并实现了支持保存点事务机制。 - 事务超时:
事务在超时前能运行多久,超过时间后,事务呗回滚。该事务超时不是所有的事务管理器支持的,如果不支持,设置此值时,将抛出异常。 - 只读状态:
只读事务不修改任何数据,我们可以对事务应用一些优化措施,提高运行性能。如果在只读事务中更改数据将抛异常。
TransactionStatus
TransactionStatus代表一个事务的具体运行状态。事务管理器可以通过该借款获取事务运行期的状态信息,也可以通过该接口间接的回滚事务,它相比于在抛出异常时回滚事务的方式更具可控性。该特性需要运行在JDBC3.0支持savepoint(保存点)的jdbc驱动上。
PlatformTransactionManager
通过JDBC的事务管理知识,我们知道事务只能被提交或回滚(或回滚到摸个保存点提交)spring的PlatformTransactionManager高层事务抽象接口,很好的描述了事务管理这个概念。1
2
3
4
5
6
7
8
9
10
11package org.springframework.transaction;
public interface PlatformTransactionManager {
TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
void commit(TransactionStatus status) throws TransactionException;
void rollback(TransactionStatus status) throws TransactionException;
}
可以看到PlatformTransactionManager只定以了3个接口方法,简单的获取事务,提交事务和回滚事务。spring将事务管理委托底层具体的持久化实现框架去完成,因此针对不同的框架spring有的不同的接口实现类,具体如下:
事务 | 说明 |
---|---|
org.springframework.orm.jpa.JpaTransactionManager | 使用JPA进行持久化时,使用该事务管理器 |
org.springframework.orm.hibernate3.HibernateTransactionManager | 使用Hibernate3.0版本时使用该事务管理器 |
org.springframework.jdbc.datasource.DataSourceTransactionManager | 使用SpringJDBC或iBatis等基于DataSource数据源的持久化技术时,使用该事务管理器 |
org.springframework.orm.jdo.JdoTransactionManager | 使用JDO进行持久化时,使用该事务管理器 |
org.springframework.transaction.jta.JtaTransactionManager |
上面的事务管理器都是对特定事务实现框架的代理,这样我们就可以通过spring所提交的高级抽象对不同种类的实现使用相同方式进行管理,而不用关心具体实现。
要实现事务管理,首先要在spring中配置好对应的事务管理器,为事务管理器指定数据源和一些事务管理控制属性。
想了解更多技术文章信息,请继续关注wiliam.s Blog,谢谢,欢迎来访!
参考资料
《Spring3.x企业应用开发实战》陈雄华 林开雄著