Spring事务 - 事务策略

一、传统事务策略
传统事务有2种策略,全局事务和局部事务。
全局事务:由应用服务器(比如WebLogic或JBoss)管理,需要底层服务器的JTA支持。
局部事务:和底层所采用的持久化技术有关。当采用JDBC持久化技术时,需要使用Connection对象来操作事务;当采用Hibernate持久化技术时,需要使用Session对象来操作事务。
全局事务可以跨多个事务性资源(典型例子是关系数据库和消息队列),使用局部事务,应用服务器不需要参与事务管理,因此不能保证跨多个事务性资源的事务的正确性。当然,实际上大部分的应用都使用单一事务性的资源。
下图是JTA全局事务、JDBC局部事务、Hibernate事务的事务操作代码对比:

从图中可以看出,当采用传统事务编程策略时,程序代码必然和具体的事务操作代码耦合。这样造成的后果是:当应用需要在不同的事务策略之间切换时,开发者必须手动修改程序代码。当使用Spring事务操作策略后,就可以改变这种现状。

二、Spring事务策略
Spring事务策略是通过PlatformTransactionManager接口体现的,该接口是Spring事务策略的核心。该接口的源代码如下:
public interface PlatformTransactionManager
{
	//平台无关的获得事务的方法
    public abstract TransactionStatus getTransaction(TransactionDefinition transactiondefinition)
        throws TransactionException;

	//平台无关的事务提交方法
    public abstract void commit(TransactionStatus transactionstatus)
        throws TransactionException;

	//平台无关的事务回滚方法
    public abstract void rollback(TransactionStatus transactionstatus)
        throws TransactionException;
}

PlatformTransactionManager是一个与任何事物策略分离的接口,随着底层不同事务策略的切换,应用必须采用不同的实现类。PlatformTransactionManager没有与任何事务资源捆绑在一起,它可以适用于任何的事务策略,结合Spring的IoC容器,可以向PlatformTransactionManager注入相关的平台特性。
PlatformTransactionManager有许多不同的实现类,应用程序面向与接口无关的平台编程,当底层采用不同的持久层技术时,系统只需使用不同的PlatformTransactionManager实现类即可--而这种切换通常由Spring容器负责管理,应用程序既无需与具体的事务API耦合,也无需与特定实现类耦合,从而将应用和持久化技术、事务API彻底分离开来。

Spring具体的事务管理由PlatformTransactionManager的不同实现类来完成。在Spring容器中配置PlatformTransactionManager Bean时,必须针对不同环境提供不同的实现类。
1.JDBC局部事务策略的配置文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<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-3.0.xsd">
	
	<!-- 定义数据源bean -->
	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
	    <!-- 指定连接数据库的驱动 -->
		<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
		<!-- 指定连接数据库的URL -->
		<property name="url" value="jdbc:oracle:****" /> 
		<property name="username" value="****" />
		<property name="password" value="****" />
		<!-- 指定连接数据库连接池的最大连接数 -->
		<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">
		<!-- 需要依赖注入dataSource的引用 -->
		<property name="dataSource" ref="dataSource" />
	</bean>
<beans>


2.容器管理的JTA全局事务的配置文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<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-3.0.xsd">
	
	<!-- 配置JNDI数据源bean -->
	<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
	    <!-- 容器管理数据源的JNDI -->
		<property name="jndiName" value="jdbc/jpetstore" />
	</bean>
	
	<!-- 使用JtaTransactionManager,该类实现PlatformTransactionManager接口 -->
	<!-- 针对采用全局事务管理的特定实现 -->
	<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager" />
<beans>

从上面的配置文件可以看出,当配置JtaTransactionManager全局事务管理策略时,只需指定事务管理器实现类即可,无需传入额外的事务资源。这是因为全局事务JTA资源由应用服务器提供,而Spring容器能自行从服务器中获取该事务资源,所以无需使用依赖注入来配置。

3.当采用Hibernate持久层访问技术时,局部事务的配置文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<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-3.0.xsd">
	
	<!-- 定义数据源bean -->
	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
	    <!-- 指定连接数据库的驱动 -->
		<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
		<!-- 指定连接数据库的URL -->
		<property name="url" value="jdbc:oracle:****" /> 
		<property name="username" value="****" />
		<property name="password" value="****" />
	</bean>
	
	<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
		<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.MySQLInnoDBDialect</prop>
				<!-- 是否根据hibernate映射创建数据表 -->
				<prop key="hibernate.hbm2ddl.auto">update</prop>
			</props>
		</property>
	</bean>
	
	<!-- 配置Hibernate的局部事务管理器,使用HibernateTransactionManager类 -->
	<!-- 该类实现PlatformTransactionManager接口,是针对采用hibernate的特定实现 -->
	<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
		<property name="sessionFactory" ref="sessionFactory" />
	</bean>
<beans>


如果底层采用Hibernate持久化技术,但事务采用JTA全局事务,则Spring配置文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<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-3.0.xsd">
	
	<!-- 配置JNDI数据源bean -->
	<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
	    <!-- 容器管理数据源的JNDI -->
		<property name="jndiName" value="jdbc/jpetstore" />
	</bean>
	
	<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
		<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.MySQLInnoDBDialect</prop>
				<!-- 是否根据hibernate映射创建数据表 -->
				<prop key="hibernate.hbm2ddl.auto">update</prop>
			</props>
		</property>
	</bean>
	
	<!-- 使用JtaTransactionManager,该类实现PlatformTransactionManager接口 -->
	<!-- 针对采用全局事务管理的特定实现 -->
	<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager" />
<beans>

从以上的配置文件可以看出,不论采用哪种持久层访技术,只要使用JTA全局事务,Spring事务管理的配置完全一样。

猜你喜欢

转载自margaret0071.iteye.com/blog/2358491