3.1 Spring事务抽象
Spring提供了一致的事务管理抽象。这个抽象是Spring最重要的抽象之一, 它有如下的优点:
? 为不同的事务API提供一致的编程模型,如JTA、JDBC、Hibernate、iBATIS数据库层 和JDO
? 提供比大多数事务API更简单的,易于使用的编程式事务管理API
? 整合Spring数据访问抽象
? 支持Spring声明式事务管理
传统上,J2EE开发者有两个事务管理的选择:全局事务或局部事务。全局事务由应用服务器管理,使用JTA。局部事务是和资源相关的:例如,
一个和JDBC连接关联的事务。全局事务可以用于多个事务性的资源(需要指出的是多数应用使用单一事务性的资源)。使用局部事务,应用服
务器不需要参与事务管理,并且不能帮助确保跨越多个资源的事务的正确性。
全局事务有一个显著的不利方面,代码需要使用JTA:一个笨重的API。此外,JTA的UserTransaction通常需要从JNDI获得,这意味着我为了JTA
需要同时使用JNDI和JTA。显然全部使用全局事务限制了应用代码的重用性,因为JTA通常只在应用服务器的环境中才能使用。
使用全局事务的比较好的方法是通过EJB的CMT (容器管理的事务): 声明式事务管理的一种形式(区别于编程式事务管理)。EJB的CMT不需
要任何和事务相关的JNDI查找,虽然使用EJB本身肯定需要使用JNDI。它消除大多数——不是全部——书写Java代码控制事务的需求。显著的
缺点是CMT绑定在JTA和应用服务器环境上,并且只有我们选择使用EJB实现业务逻辑,或者至少处于一个事务化EJB的外观(Facade)后才能使
用它。
局部事务容易使用,但也有明显的缺点:它们不能用于多个事务性资源,并且趋向侵入的编程模型。例如,使用JDBC连接事务管理的代码不能
用于全局的JTA事务中。
Spring解决了这些问题。它使应用开发者能够使用在任何环境下使用一致的编程模型。你可以只写一次你的代码,这在不同环境下的不同事务
管理策略中很有益处。Spring同时提供声明式和编程式事务管理。
使用编程式事务管理,开发者直接使用Spring事务抽象,这个抽象可以使用在任何底层事务基础之上。使用首选的声明式模型,开发者通常书 写很少的事务相关代码,因此不依赖Spring或任何其他事务API。
Spring同时支持两种事务编程模型:声明式和编程式。对于声明式事务而言,Spring支持各种事务管理器(EJB仅支持JTA),借助于Spring
AOP模块,能够实现Spring提供的声明式事务支持(企业应用在完成业务逻辑操作时,需要借助于事务服务,所以将事务抽象作为AOP的Aspect
是很合理的)。Spring提供了TransactionProxyFactoryB ean类,供实现声明式事务使用。对于编程式事务,Spring也提供了各种事务管理器。Spring提供的所有的事务管理器,仅仅是对现有的事务实现API(比如,Hibernate、JDBC、JTA)进行封装,其本身并没有提供具体的事务实现
。所有的事务管理器中,最基本的是PlatformTransactionManag er接口。
使用编程式事务管理,开发者直接使用Spring事务抽象,这个抽象可以使用在任何底层事务基础之上。使用首选的声明式模型,开发者通常书 写很少的事务相关代码,因此不依赖Spring或任何其他事务API。
Spring同时支持两种事务编程模型:声明式和编程式。对于声明式事务而言,Spring支持各种事务管理器(EJB仅支持JTA),借助于Spring
public interface PlatformTransactionManag er {
TransactionStatus getTransaction(TransactionDefinition definition)
throws TransactionException;
void commit(TransactionStatus status) throws TransactionException;
void rollback(TransactionStatus status) throws TransactionException;
}
Spring为它提供了若干个实现,供不同的事务实现使用。
例如:
HibernateTransactionMana
DataSourceTransactionMan
JtaTransactionManager:JTA事务
以Hibernate为例,就是借助于HibernateTransactionMana
<bean id="dataSource"
destroy-method="close">
<property name="driverClassName"><value>${jdbc.driverClassName}</value></property>
<property name="url"><value>${jdbc.url}</value></property>
<property name="username"><value>${jdbc.username}</value></property>
<property name="password"><value>${jdbc.password}</value></property>
</bean>
<bean id="sessionFactory" lang="EN-US" style="font-size:9pt"> <property name="dataSource"><ref local="dataSource"/></property>
<property name="mappingResources">
<value>org/springframework/samples/petclinic/hibernate/petclinic.hbm.xml</value>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
</props>
</property>
</bean>
<bean id="transactionManager"
lang="EN-US" style="font-size:9pt"> <property name="sessionFactory"><ref local="sessionFactory"/></property>
</bean>