螺 丝 钉 阅读(83) 评论(0)

 

 

上一节了解了全局事务与局部事务以及Spring提供的两种事务模式:编程式事务与声明式事务。

    不论是编程式的事务处理,还是声明式的事务处理。他们都要对局部事务和全局事务以支持,也就是说要对JDBC进行支持、ORM框架,同时也要对JTA进行支持。他们的公共部分是commit,rollback。通过这一节的了解,我相信以后配置Spring事务时,就不需要在去网上查资料了或者去查Spring的参考文档了。

    因此,Spring设计了如下的事务管理框架:

 

 

 从上面的类图中和容易可以看出分为三部分:PlatformTransactionManager是事务管理的核心。它可以根据TransactionDefinition获取到TransactionStatus对象,然后在事务处理过程中酌情的执行commit或者rollback。

==============================================================

接下来就来看看这三个接口是怎么描述的:

PlatformTransactionManager

 

/**

 * This is the central interface in Spring's transaction infrastructure.

 * Applications can use this directly, but it is not primarily meant as API:

 * Typically, applications will work with either TransactionTemplate or

 * declarative transaction demarcation through AOP.

 *

 * <p>For implementors, it is recommended to derive from the provided

 * {@link org.springframework.transaction.support.AbstractPlatformTransactionManager}

 * class, which pre-implements the defined propagation behavior and takes care

 * of transaction synchronization handling. Subclasses have to implement

 * template methods for specific states of the underlying transaction,

 * for example: begin, suspend, resume, commit.

 *

 * <p>The default implementations of this strategy interface are

 * {@link org.springframework.transaction.jta.JtaTransactionManager} and

 * {@link org.springframework.jdbc.datasource.DataSourceTransactionManager},

 * which can serve as an implementation guide for other transaction strategies.
*/
View Code

这个接口是Spring中事务管理的基础框架的核心。在程序中可以直接使用这个接口,但是不推荐这么做。一般来说,在应用程序中,有两种使用方式:通过编程的方式使用TransactionTemplate来或通过AOP来使用声明式事务管理。这一节并不会去了解这两种方式,而是了解他们共有的这部分基础框架。 

 

这个接口的实现类AbstractPlatformTransactionManager 中定义了事务的传播行为,并且考虑到了事务的同步处理。AbstractPlatformTransactionManager的子类必须实现下面几个模板方法:begin,suspend,resume,commit。

 

 

TransactionDefinition

 Spring是如何定义事务的呢?

public interface TransactionDefinition {

int getPropagationBehavior();

int getIsolationLevel();

int getTimeout();

boolean isReadOnly();

String getName();

}

这个接口用于定义Transaction的属性。常用的属性有:

·Propagation 传播行为:用于定义有关联的事务之间的处理机制。传播行为可以分为:Required、Supports、Mandatory、Requires_new、Not_support、Never、Nested。

其实也就是当前要执行的操作是否需要事务处理,是否在当前已存在的事务中执行,是否开启新的事务。

 

1Required:只要保证有事务就行。若接下来要做的操作,已经在一个事务中,就不用开启事务。如果不在事务中,就开启一个新的事务。也就是说,要保证要执行的操作在一个事务中。

 

2Supports:支持事务。就是说事务是可有可无的。在Supports的事务的操作时,如果操作不处于事务中,不会去创建一个新的。使用Support时的小心。

 

3Mandatory:强制性。就是说必须在已有的事务中,没有就抛异常。和Required明显不一样。也就是执行时,当前事务得是存在的。

 

4Requireds_New:这个是说事务肯定得有,并且必须是新创建的。如果已经在当前事务中,就先将当前事务挂起。

 

5Not_Support:不支持事务。如果当前事务存在,宁可以非事务的方式处理。

 

6Never:不能有事务。如果当前事务存在,抛异常。

 

7Nested:嵌入到当前事务中。当前事务必须存在。

 

 

·Isolation:隔离级别。前面讲过事务的几个特性中,有一个是隔离性。就是说多个共存的事务是相互隔离的。例如,当前没有提交的事务,能否被其他事务看到。

隔离级别主要处理一些三种不期望情况:

 

脏读:就是说一个事务T1来读取表记录,同时也有其他的事务T2来修改这些(条)记录,但是T1读的时候,其他事务T2已经对表记录改变了,但未提交,如果其他事务T2再回滚,那么这个事务T1读到的数据就是脏数据,这就是脏读。

 

不可重复读:就是说第一个事务T1读取表某条记录,紧接着事务T2调整了这记录并提交,事务T1第二次读取这记录。T1两次读到的数据不一致,这就是不可重复读。针对单条记录。

 

虚读:就是说第一个事务T1读取表某些(where条件下的多条记录)记录,紧接着事务T2调整了这记录并提交,事务T1第二次读取这记录。T1两次读到的数据不一致,这就是不可重复读。针对多条记录。

 

Spring中提供的隔离级别的支持:

1)Default

2)Read_Uncommited,当前事务没有提交时,其他事务可以读取数据。在这种隔离级别是,就会有可能发生脏读、不重复读、虚读 等情况。

3)Read_Commited:读到的是其他事务提交后的数据,避免了脏读的发生。还会出现不可重复读和虚读。

4)Repeatable_Read:可重复读。这种情况下,避免了脏读、不可重复读的情况。

5)Serializable:避免三种情况。

 

 

 

·TimeOut:事务运行超时(超过指定时限)后自动回滚。-1代表没有时限。

 

·ReadOnly_Status。只读事务。

 

Spring框架就是通过TransactionDefinition来定义事务的。

 

 

TransactionStatus

 

public interface TransactionStatus extends SavepointManager {
    boolean isNewTransaction();
    boolean hasSavepoint();
    void setRollbackOnly();
    boolean isRollbackOnly();
    void flush();
    boolean isCompleted();
}

 TransactionStatus,用于从代码上控制事务,提供了事务状态查询功能。

 PlatformTransactionManager如何使用??

在Spring中,不论使用哪种模式(编程式、声明式)的事务管理,正确的定义PlatformTransactionManager的实现类,是很重要的。通常是通过Spring的DI定义TransactionManager的。这点对于两种模式的事务管理都是可用的。

 

根据不同的情况,可以定义各种事务管理:

 

 

 

譬如说,可以定义

 

 

 

 同时还可以集成Hibernate等ORM框架,图我就不贴了。