风故故,也依依

Stand still in the wind.

导航

Spring的事务(1)

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  阅读(241)  评论(0编辑  收藏  举报