Spring事务的架构 .

来源:互联网 发布:知乎何炅和撒贝宁关系 编辑:程序博客网 时间:2024/05/17 06:09
Spring的事务框架设计理念的基本原则是:让事务管理的关注点与数据访问关注点相分离。从此之后,事务管理就是事务管理,数据访问只关心数据访问,再也不用因为它们之间的纠缠而烦恼

 

org.springframework.transaction.PlatformTransactionManager是Spring事务抽象架构的核心接口,它的主要作用是为应用程序提供事务界定的统一方式。既然事务界定的需要很简单,那么PlatformTransactionManager的定义看起来也不会过于复杂.

PlatformTransactionManager是整个事务抽象策略的顶层接口,它就好像我们的战略蓝图,而战略的具体实施则将由相应的PlatformTransactionManager实现类来执行

Spring的事务框架针对不同的数据访问方式以及全局事务场景,提供了相应的Platform- TransactionManager实现类。在每个实现类的职责完成之后,Spring事务框架的"统一大业"就完成了。在深入了解各个PlatformTransactionManager实现类的奥秘之前,不妨先考虑一下,如果让我们来实现一个PlatformTransactionManager,要如何去做?

 

我们通常都是将事务管理放在Service层,而将数据访问逻辑放在DAO层。这样做的目的是,可以不用因为将事务管理代码放在DAO层,而降低数据访问逻辑的重用性,也可以在Service层根据相应逻辑,来决定提交或者回滚事务。一般的Service对象可能需要在同一个业务方法中调用多个数据访问对象的方法

 对于我们要实现的针对JDBC的PlatformTransactionManager,只需要在事务开始的时候,通过我们的TransactionResourceManager将java.sql.Connection绑定到线程,然后在事务结束的时候解除绑定即可

 

Spring的事务抽象包括3个主要接口,即PlatformTransactionManager、TransactionDefinition以及TransactionStatus,

这3个接口以org.springframe- work.transaction.PlatformTran- sactionManager为中心,互为犄角,多少有点儿"晋西北铁三角"的味道。

org.springframework.transac- tion.PlatformTransactionManager负责界定事务边界。

org.spring- framework.transaction.TransactionDefinition负责定义事务相关属性,包括隔离级别、传播行为等。org.springframework.transaction.PlatformTransactionManager将参照org.springframe- work.transaction.TransactionDefinition的属性定义来开启相关事务。

事务开启之后到事务结束期间的事务状态由org.springframework.transaction.TransactionStatus负责,

我们也可以通过org.springframework.transaction.TransactionStatus对事务进行有限的控制

 

1. TransactionDefinition简介

org.springframework.transaction.TransactionDefinition主要定义了有哪些事务属性可以指定,这包括:

事务的隔离(Isolation)级别

事务的传播行为(Propagation Behavior)

事务的超时时间(Timeout)

是否为只读(ReadOnly)事务

TransactionDefinition内定义了如下5个常量用于标志可供选择的隔离级别。

ISOLATION_DEFAULT。如果指定隔离级别为ISOLATION_DEFAULT,则表示使用数据库默认的隔离级别,通常情况下是Read Committed。

ISOLATION_READ_UNCOMMITTED。对应Read Uncommitted隔离级别,无法避免脏读,不可重复读和幻读。

ISOLATION_READ_COMMITTED。对应Read Committed隔离级别,可以避免脏读,但无法避免不可重复读和幻读。

ISOLATION_REPEATABLE_READ。对应Repeatable read隔离级别,可以避免脏读和不可重复读,但不能避免幻读。

ISOLATION_SERIALIZABLE。对应Serializable隔离级别,可以避免所有的脏读,不可重复读以及幻读,但并发性效率最低。

 

 

针对事务的传播行为,TransactionDefinition提供了以下几种选择,除了PROPAGATION_ NESTED是Spring特有的外,其他传播行为的语义与CMT基本相同。

PROPAGATION_REQUIRED。如果当前存在一个事务,则加入当前事务。如果不存在任何事务,则创建一个新的事务。总之,要至少保证在一个事务中运行。

PROPAGATION_REQUIRED通常作为默认的事务传播行为。

PROPAGATION_SUPPORTS。如果当前存在一个事务,则加入当前事务。如果当前不存在事务,则直接执行。对于一些查询方法来说,PROPAGATION_SUPPORTS通常是比较合适的传播行为选择。如果当前方法直接执行,那么不需要事务的支持。如果当前方法被其他方法调用,而其他方法启动了一个事务,使用PROPAGATION_SUPPORTS可以保证当前方法能够加入当前事务,并洞察当前事务对数据资源所做的更新。比如,A.service()会首先更新数据库,然后调用B.service()进行查询,那么,如果B.service()是

PROPAGATION_SUPPORTS的传播行为,就可以读取A.service()之前所做的最新更新结果(如图19-6所示)。而如果使用稍后所提到的

PROPAGATION_NOT_SUPPORTED,则B.service()将无法读取最新的更新结果,因为A.service()的事务在这时还没有提交(除非隔离级别是Read Uncommitted)。

PROPAGATION_MANDATORY。PROPAGATION_MANDATORY强制要求当前存在一个事务,如果不存在,则抛出异常。如果某个方法需要事务支持,但自身又不管理事务提交或者回滚,那么比较适合使用PROPAGATION_MANDATORY。可以参照Java Transaction Design Strategies一书中对REQUIRED和MANDATORY两种传播行为的比较,来更深入地了解PROPAGATION_ MANDATORY可能的应用场景。

 

PROPAGATION_REQUIRES_NEW。不管当前是否存在事务,都会创建新的事务。如果当前存在事务,会将当前的事务挂起(Suspend)。如果某个业务对象所做的事情不想影响到外层事务,PROPAGATION_REQUIRES_NEW应该是合适的选择。比如,假设当前的业务方法需要向数据库中更新某些日志信息,但即使这些日志信息更新失败,我们也不想因为该业务方法的事务回滚,而影响到外层事务的成功提交。因为这种情况下,当前业务方法的事务成功与否对外层事务来说是无关紧要的。

PROPAGATION_NOT_SUPPORTED。不支持当前事务,而是在没有事务的情况下执行。如果当前存在事务的话,当前事务原则上将被挂起(Suspend),但这要看对应的PlatformTransaction- Manager实现类是否支持事务的挂起。更多情况请参照TransactionDefinition的Javadoc文档。PROPAGATION_NOT_SUPPORTED与

PROPAGATION_SUPPORTS之间的区别,可以参照PROPAGATION_ SUPPORTS部分的实例内容。

PROPAGATION_NEVER。永远不需要当前存在事务,如果存在当前事务,则抛出异常。

PROPAGATION_NESTED。如果存在当前事务,则在当前事务的一个嵌套事务中执行,否则与PRO- PAGATION_REQUIRED的行为类似,即创建新的事务,在新创建的事务中执行。PROPAGATION_ NESTED粗看起来好像与PROPAGATION_REQUIRES_NEW的行为类似,实际上二者是有差别的。PROPAGATION_REQUIRES_NEW创建的新事务与外层事务属于同一个"档次",即二者的地位是相同的。当新创建的事务运行的时候,外层事务将被暂时挂起。而PROPAGATION_NESTED创建的嵌套事务则不然,它是寄生于当前外层事务的,它的地位比当前外层事务的地位要小一号。当内部嵌套事务运行的时候,外层事务也是处于active状态,图19-7演示了PROPAGATION_

REQUIRES_NEW和PROPAGATION_NESTED中涉及的多个事务相互之间的地位。

0 0
原创粉丝点击