上一节了解了全局事务与局部事务以及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. */
这个接口是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。
其实也就是当前要执行的操作是否需要事务处理,是否在当前已存在的事务中执行,是否开启新的事务。
1)Required:只要保证有事务就行。若接下来要做的操作,已经在一个事务中,就不用开启事务。如果不在事务中,就开启一个新的事务。也就是说,要保证要执行的操作在一个事务中。
2)Supports:支持事务。就是说事务是可有可无的。在Supports的事务的操作时,如果操作不处于事务中,不会去创建一个新的。使用Support时的小心。
3)Mandatory:强制性。就是说必须在已有的事务中,没有就抛异常。和Required明显不一样。也就是执行时,当前事务得是存在的。
4)Requireds_New:这个是说事务肯定得有,并且必须是新创建的。如果已经在当前事务中,就先将当前事务挂起。
5)Not_Support:不支持事务。如果当前事务存在,宁可以非事务的方式处理。
6)Never:不能有事务。如果当前事务存在,抛异常。
7)Nested:嵌入到当前事务中。当前事务必须存在。
·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框架,图我就不贴了。
Spring源码阅读:Spring事务管理的基础