6.3 Spring的事务
Spring的事务管理不需与任何特定的事务API耦合。对不同的持久层访问技术,编程式事务提供一致的事务编程风格,通过模板化的操作一致性地管理事务。声明式事务基于Spring AOP实现,却并不需要程序开发者成为AOP专家,亦可轻易使用Spring的声明式事务管理。
6.3.1 Spring支持的事务策略
Spring事务策略是通过PlatformTransactionManager接口体现的,该接口是Spring事务策略的核心。该接口的源代码如下:
public interface PlatformTransactionManager
{
//平台无关的获得事务的方法
TransactionStatus getTransaction(TransactionDefinition definition)
throws TransactionException;
//平台无关的事务提交方法
void commit(TransactionStatus status) throws TransactionException;
//平台无关的事务回滚方法
void rollback(TransactionStatus status) throws TransactionException;
}
PlatformTransactionManager是一个与任何事务策略分离的接口,随着底层不同事务策略切换,应用必须采用不同的实现类。PlatformTransactionManager接口没有与任何事务资源捆绑在一起,它可以适应于任何的事务策略,结合Spring的IoC容器,可以向PlatformTransactionManager注入相关的平台特性。
PlatformTransactionManager接口有许多不同的实现类,应用程序面向与平台无关的接口编程,对不同平台的底层支持,由PlatformTransactionManager接口的实现类完成。从而,应用程序无须与具体的事务API耦合。因此,使用PlatformTransactionManager接口,可将代码从具体的事务API中解耦出来。
即使使用特定容器管理的JTA,代码依然无须执行JNDI查找,无须与特定的JTA资源耦合在一起。通过配置文件,JTA资源传给PlatformTransactionManager的实现类。因此,程序的代码可在JTA事务管理和非JTA事务管理之间轻松切换。
在PlatformTransactionManager接口内,包含一个getTransaction(TransactionDefinition definition)方法,该方法根据一个TransactionDefinition参数,返回一个TransactionStatus对象。TransactionStatus对象表示一个事务。TransactionStatus被关联在当前执行的线程。
getTransaction(TransactionDefinition definition)返回的TransactionStatus对象,可能是一个新的事务,也可能是一个已经存在的事务对象。如果当前执行的线程已经处于事务管理下,返回当前线程的事务对象,否则,返回当前线程的调用堆栈已有的事务对象。
TransactionDefinition接口定义了一个事务规则,该接口必须指定如下几个属性值:
● 事务隔离,当前事务和其他事务的隔离程度。例如,这个事务能否看到其他事务未提交的数据等。
● 事务传播,通常,在事务中执行的代码都会在当前事务中运行。但是,如果一个事务上下文已经存在,有几个选项可指定该事务性方法的执行行为。例如,大多数情况下,简单地在现有的事务上下文中运行;或者挂起现有事务,创建一个新的事务。Spring提供EJB CMT(Contain Manager Transaction,容器管理事务)中所有的事务传播选项。
● 事务超时,事务在超时前能运行多久。事务的最长持续时间。如果事务一直没有被提交或回滚,将在超出该时间后,系统自动回滚事务。
● 只读状态,只读事务不修改任何数据。在某些情况下(例如使用Hibernate时),只读事务是非常有用的优化。
TransactionStatus代表事务本身,它提供了简单的控制事务执行和查询事务状态的方法。这些方法在所有的事务API中都是相同的。TransactionStatus接口的源代码如下:
public interface TransactionStatus
{
//判断事务是否是新建的事务
boolean isNewTransaction();
//设置事务回滚
void setRollbackOnly();
//查询事务是否已有回滚标志
boolean isRollbackOnly();
}
Spring的事务管理由PlatformTransactionManager的不同实现类完成。在Spring上下文中配置PlatformTransactionManager Bean时,必须针对不同环境提供不同的实现类。
下面提供不同的持久层访问环境,及其对应的PlatformTransactionManager实现类的 配置。
JDBC数据源的局部事务策略:
<?xml version="1.0" encoding="GBK"?>
<!-- 指定Spring配置文件的根元素,以及Spring配置文件的Schema信息 -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 定义数据源Bean,使用C3P0数据源实现 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<!-- 指定连接数据库的驱动 -->
<property name="driverClass" value="com.mysql.jdbc.Driver"/>
<!-- 指定连接数据库的URL -->
<property name="jdbcUrl" value="jdbc:mysql://localhost/j2ee"/>
<!-- 指定连接数据库的用户名 -->
<property name="user" value="root"/>
<!-- 指定连接数据库的密码 -->
<property name="password" value="32147"/>
<!-- 指定连接数据库连接池的最大连接数 -->
<property name="maxPoolSize" value="40"/>
<!-- 指定连接数据库连接池的最小连接数 -->
<property name="minPoolSize" value="1"/>
<!-- 指定连接数据库连接池的初始化连接数 -->
<property name="initialPoolSize" value="1"/>
<!-- 指定连接数据库连接池的连接最大空闲时间 -->
<property name="maxIdleTime" value="20"/>
</bean>
<!-- 配置JDBC数据源的局部事务管理器 -->
<!-- 使用DataSourceTransactionManager 类,该类实现PlatformTransactionManager接口 -->
<!-- 针对采用数据源连接的特定实现 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.
DataSourceTransactionManager">
<!-- DataSourceTransactionManager bean需要依赖注入一个DataSource
bean的引用 -->
<property name="dataSource" ref="dataSource"/>
</bean>
</beans>
对于容器管理JTA数据源,全局事务策略的配置文件如下:
<?xml version="1.0" encoding="GBK"?>
<!-- 指定Spring配置文件的根元素,以及Spring配置文件的Schema信息 -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 配置JNDI数据源Bean -->
<bean id="dataSource" class="org.springframework.jndi.
JndiObjectFactoryBean">
<!-- 容器管理数据源的JNDI -->
<property name="jndiName" value="jdbc/jpetstore"/>
</bean>
<!-- 使用JtaTransactionManager类,该类实现PlatformTransactionManager接
口 -->
<!-- 针对采用全局事务管理的特定实现 -->
<!-- JtaTransactionManager不需要知道数据源,或任何其他特定资源 -->
<!-- 因为它使用容器的全局事务管理 -->
<bean id="transactionManager"
class="org.springframework.transaction.jta.
JtaTransactionManager" />
</beans>
对于采用Hibernate持久层访问策略时,局部事务策略的配置文件如下:
<?xml version="1.0" encoding="GBK"?>
<!-- 指定Spring配置文件的根元素,以及Spring配置文件的Schema信息 -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 定义数据源Bean,使用C3P0数据源实现 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.
ComboPooledDataSource" destroy-method="close">
<!-- 指定连接数据库的驱动 -->
<property name="driverClass" value="com.mysql.jdbc.Driver"/>
<!-- 指定连接数据库的URL -->
<property name="jdbcUrl" value="jdbc:mysql://localhost/j2ee"/>
<!-- 指定连接数据库的用户名 -->
<property name="user" value="root"/>
<!-- 指定连接数据库的密码 -->
<property name="password" value="32147"/>
<!-- 指定连接数据库连接池的最大连接数 -->
<property name="maxPoolSize" value="40"/>
<!-- 指定连接数据库连接池的最小连接数 -->
<property name="minPoolSize" value="1"/>
<!-- 指定连接数据库连接池的初始化连接数 -->
<property name="initialPoolSize" value="1"/>
<!-- 指定连接数据库连接池的连接最大空闲时间 -->
<property name="maxIdleTime" value="20"/>
</bean>
<!-- 定义Hibernate的SessionFactory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.
LocalSessionFactoryBean">
<!-- 依赖注入SessionFactory所需的数据源,正是上文定义的dataSource -->
<property name="dataSource" ref="dataSource"/>
<!-- mappingResources属性用来列出全部映射文件 -->
<property name="mappingResources">
<list>
<!-- 以下用来列出所有的PO映射文件 -->
<value>lee/MyTest.hbm.xml</value>
</list>
</property>
<!-- 定义Hibernate的SessionFactory的属性 -->
<property name="hibernateProperties">
<props>
<!-- 指定Hibernate的连接方言 -->
<prop key="hibernate.dialect">org.hibernate.dialect.
MySQLDialect</prop>
<!-- 是否根据Hibernate映射创建数据表时,选择create、update、
create-drop -->
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
</bean>
<!-- 配置Hibernate的局部事务管理器 -->
<!-- 使用HibernateTransactionManager类,该类是PlatformTransactionManager
接口,针对采用Hibernate持久化连接的特定实现 -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.
HibernateTransactionManager">
<!-- HibernateTransactionManager Bean需要依赖注入一个
SessionFactorybean的引用 -->
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
</beans>
对于采用Hibernate持久层访问策略时,全局事务策略的配置文件如下:
<?xml version="1.0" encoding="GBK"?>
<!-- 指定Spring配置文件的根元素,以及Spring配置文件的Schema信息 -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 配置JNDI数据源Bean -->
<bean id="dataSource" class="org.springframework.jndi.
JndiObjectFactoryBean">
<!-- 容器管理数据源的JNDI -->
<property name="jndiName" value="jdbc/jpetstore"/>
</bean>
<!--定义Hibernate的SessionFactory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.
LocalSessionFactoryBean">
<!-- 依赖注入SessionFactory所需的数据源,正是上文定义的dataSource Bean -->
<property name="dataSource" ref="dataSource"/>
<!-- mappingResources属性用来列出全部映射文件 -->
<property name="mappingResources">
<list>
<!-- 以下用来列出所有的PO映射文件 -->
<value>lee/MyTest.hbm.xml</value>
</list>
</property>
<!-- 定义Hibernate的SessionFactory的属性 -->
<property name="hibernateProperties">
<props>
<!-- 指定Hibernate的连接方言 -->
<prop key="hibernate.dialect">org.hibernate.dialect.
MySQLDialect</prop>
<!-- 是否根据Hiberante映射创建数据表时,选择create、update、
create-drop -->
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
</bean>
<!-- 使用JtaTransactionManager类,该类是PlatformTransactionManager接口,
针对采用数据源连接的特定实现 -->
<!-- JtaTransactionManager不需要知道数据源,或任何其他特定资源,
因为使用容器的全局事务管理 -->
<bean id="transactionManager"
class="org.springframework.transaction.jta.
JtaTransactionManager" />
</beans>
不论采用哪种持久层访问技术,只要使用JTA数据源,Spring事务管理器的配置都是一样的,因为它们都采用的是全局事务管理。
可以看到,仅仅通过配置文件的修改,就可以在不同的事务管理策略间切换,即使从局部事务到全局事务的切换。
提示:Spring所支持的事务策略非常灵活,Spring的事务策略允许应用程序在不同事务策略之间自由切换,即使需要在局部事务策略和全局事务策略之间切换,只需要修改配置文件,而应用程序的代码无须任何改变。这种灵活的设计,又何尝不是因为面向接口编程带来的优势,可见面向接口编程给应用程序更好的适应性。
posted on 2009-07-19 10:18
jadmin 阅读(72)
评论(0) 编辑 收藏