一、简介
Spring Framework对事务管理的强大支持,是我们使用它的一个很重要的理由。Spring Framework提供了一致的抽象的事务管理,有以下优势:
(1)为不同的事务API(JPA,JTA,Hibernate,JDBC,JDO)提供了一个一致的编程模型;
(2)支持声明式事务管理(Declarative tansaction management);注:声明式事务管理指的是由容器来管理事务
(3)为编程式事务管理提供了一个更简单的API。(相比其他复杂的事务API,比如JTA);注:编程式事务管理指的是由用户编写的bean来管理事务。
(4)与Spring的数据访问抽象(Spring‘s data access abstraction)完美集成。
二、Spring Framework事务支持模型的优点
传统上,JEE开发者有两种事务管理可以选择:全局事务和本地事务。不过两种都有其局限性,而Spring的事务管理支持解决了这两种方式的局限性。
(1)全局事务:涉及多种事务性资源,其中单独的一个资源无法实现全局事务,必须有一个协调程序来统一协调各个资源的操作才能实现。全局事务的协调程序称为事务协调器或者事务管理器,通常是JavaEE容器来充当。JavaEE容器通过JTA来管理全局事务,但是JTA使用起来非常笨重(部分原因是由它的异常模型引起的),而且JTA需要使用JNDI。之前,使用全局事务的方式是通过EJB CMT(Container managed tansaction)。CMT是声明式事务管理方式的一种,但是CMT是和JTA和应用服务器环境绑定的。
(2)本地事务:只涉及单一的事务性资源,绝大多数程序使用的都是本地事务,无需JEE容器的支持,事务性资源本身即可提供(如JDBC数据库连接上的事务)。虽然本地事务很容易使用,但是它不能处理多种事务性资源,而且对编程模型来说有侵入性。
(3)Spring的一致编程模型:Spring解决了上面两种管理方式的局限性,它使开发者能够在任何环境中使用一致的编程模型。Spring支持声明式事务管理和编程式事务管理。大部分用户更倾向使用声明式事务管理,它也是大部分情况下推荐使用的一种事务管理方式。
使用编程式事务管理,开发者使用Spring的事务抽象,它可以运行在任何的事务基础设施之上。使用声明式事务管理,开发者通常不需要或者只是少量的编写事务相关的代码,而不需要依赖于Spring的事务API或者其他任何的事务API。
三、理解Spring的事务抽象
Spring事务抽象的关键是事务策略,一个事务策略是由接口org.springframework.transaction.PlatformTransactionManager定义的:
public interface PlatformTransactionManager { TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException; void commit(TransactionStatus status) throws TransactionException; void rollback(TransactionStatus status) throws TransactionException; }
不管你使用的是Spring的编程式还是声明式事务管理,定义一个正确的PlatformTransactionManager实现是都是至关重要的。我们通过使用依赖注入来定义这个实现。PlatformTransactionManager实现一般需要知道它在什么环境下工作,是JDBC,JTA,Hibernate等等。以JDBC环境为例定义一个PlatformTransactionManager:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroymethod="close"> <property name="driverClassName" value="${jdbc.driverClassName}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </bean> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean>
如果使用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" xmlns:jee="http://www.springframework.org/schema/jee" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd"> <jee:jndi-lookup id="dataSource" jndi-name="jdbc/jpetstore"/> <bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager"/> <!-- other <bean/> definitions here --> </beans>
使用Hibernate环境的例子:
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="mappingResources"> <list> <value>org/springframework/samples/petclinic/hibernate/petclinic.hbm.xml</value> </list> </property> <property name="hibernateProperties"> <value>hibernate.dialect=${hibernate.dialect}</value> </property> </bean> <bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean>
以上所有的情况,应用的代码都不需要改变,你通过改变配置就可以改变事物的管理方式,即使这个改变是本地事务与全局事务之间的改变。
Spring Framework--Data Access(1)--Transaction Management(1) - 概述,布布扣,bubuko.com
Spring Framework--Data Access(1)--Transaction Management(1) - 概述