`

Spring 事务 (二) Spring 声明式事务 配置

阅读更多

Spring 事务 (二) Spring 声明式事务 配置

 

2.  Spring 声明式事务 配置

 

     由Spring 事务 (一)知道,Spring事务基本概念中,最重要的是

     PlatformTransactionManager,它的

     TransactionStatus getTransaction(TransactionDefinition definition)

     方法根据一个TransactionDefinition生成TransactionStatus.

     这样可知,配置事务,首先需要配置一个PlatformTransactionManager信息,

     然后需要配置 TransactionDefinition信息.而TransactionStatus是返回的值,

     根据前面两个配置由TransactionStatus对象获取相应的配置信息.

     

     所以配置时,主要配置PlatformTransactionManager,TransactionDefinition.

     

     Spring的事务功能由事务代理完成.

     一般的流程是:

     先编写业务接口,

     然后编写一个业务接口的实现类,并配置为bean(targetBean),

     再配置一个TransactionProxyFactoryBean,得到一个代理bean(代理targetBean),

     然后客户端代码中,通过代理bean的id来调用getBean方法,得到TransactionProxyFactoryBean配置的bean.

     

     配置这个代理bean需要传入一个事务管理器(PlatformTransactionManager),一个目标bean(targetBean),

     并指定事务代理的事务属性.

     

     上述配置TransactionProxyFactoryBean的方式为显示的,即配置一个targetBean,和一个有事务行为的代理bean,

     实际上配置了两个bean,而原来的targetBean是不直接使用的,假如代码中不小心使用了targetBean,则会产生问题.

     

     因此Spring还提供了一种基于tx命名空间的方式来配置事务代理bean,这种配置类似于AOP配置,只配置一个bean,

     当根据bean id使用getBean()获取bean实例时,Spring容器自动提供事务代理bean的实例.

     

     http://www.ibm.com/developerworks/cn/education/opensource/os-cn-spring-trans/section5.html

     上面链接中,还讨论了使用拦截器实现的事务(非事务代理bean方式),供参考.

     

   

2.1  PlatformTransactionManager配置

 

     PlatformTransactionManager配置,根据不同数据源的使用,以及是局部事务还是全局事务 来分类,

     主要有下面几种配置方式:

     

2.1.1 数据源使用JDBC数据源的局部事务,使用DataSourceTransactionManager类

 

     

<!-- 数据源使用JDBC数据源的局部事务,使用DataSourceTransactionManager类 -->
     <!-- DataSource配置,可配置为c3p0连接池等,这里省略 -->
     <bean id="dataSource" ...>...</bean>
     <bean id="transactionManager" 
           class="org.springframework.jdbc.datasouce.DataSouceTransactionManager">
       <!-- 配置DataSourceTransactionManager时,需要依赖注入DataSource的引用 -->
       <property name="dataSource" ref="dataSource"/>      
     </bean>

 

 

2.1.2  采用全局事务的特定实现

    

     

<!-- 采用全局事务的特定实现 -->
     <bean id="transactionManager" 
           class="org.springframework.transaction.jta.JtaTransactionManager" />

 
 

     

     上面配置,无需指定datasource. 全局事务有JTA实现(比如有的容器weblogic等实现JTA,

     也有专门的开源框架实现JTA,如JOTM)     

 

2.1.3 使用Hibernate的配置

 

     

<!-- 使用Hibernate的配置 -->
     <!-- DataSource配置,可配置为c3p0连接池等,这里省略 -->
     <bean id="dataSource" ...>...</bean>
     <!-- Hibernate的SessionFactory配置,这里省略 --> 
     <bean id="sessionFactory" ...>...</bean>
     <bean id="transactionManager"
           <!-- 针对Hibernate的特定实现类 --> 
           class="org.springframework.orm.hibernate3.HibernateTransactionManager">
       <!-- 配置Hibernate时,需要依赖注入SessionFactory的引用 -->
       <property name="sessionFactory" ref="sessionFactory"/>      
     </bean>

 

     

3 配置 TransactionProxyFactoryBean

 

3.1 配置一个targetBean(业务逻辑bean),和一个有事务行为的代理bean

 

     

<!-- 数据源使用JDBC数据源的局部事务,使用DataSourceTransactionManager类 -->
     <!-- DataSource配置,可配置为c3p0连接池等,这里省略 -->
     <bean id="dataSource" ...>...</bean>
     <bean id="transactionManager" 
           class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
       <!-- 配置DataSourceTransactionManager时,需要依赖注入DataSource的引用 -->
       <property name="dataSource" ref="dataSource"/>      
     </bean>
     
     <!-- 一个业务逻辑bean -->
     <bean id="newsDao" class="xxx.xxx.NewsDao" >
       <property name="ds" ref="dataSource" />
     </bean>
     
     <!-- 为业务逻辑bean配置事务代理 -->
     <bean id="newsDaoTran" class="org.springframework.transaction.intereptor.TransactionProxyFactoryBean">
       <!-- 注入事务管理器 -->
       <property name="transactionManager" ref="transactionManager" />
       <!-- 指定被代理的目标bean -->
       <property name="target" ref="newDao" />
       <!-- 指定事务属性 -->
       <property name="transactionAttributes">
         <props>
           <prop key="*">PROPAGATION_REQUIRED</prop>
         </props>
       </property>
     </bean>

 

     

     上面transactionAttributes标示注入的是一个properties类型的属性.

     key表示方面名称,可以使用通配符,

     value表示事务规则:

     指定事务属性的取值有较复杂的规则,具体的书写规则如下:

     

     传播行为 [,隔离级别] [,只读属性] [,超时属性] [不影响提交的异常] [,导致回滚的异常]

     

     只有传播行为是必须指定的,其他的可以省略(取默认值)

     

      传播行为是唯一必须设置的属性,其他都可以忽略,Spring为我们提供了合理的默认值。

      传播行为的取值必须以“PROPAGATION_”开头,

        具体包括:

        PROPAGATION_MANDATORY、

        PROPAGATION_NESTED、

        PROPAGATION_NEVER、

        PROPAGATION_NOT_SUPPORTED、

        PROPAGATION_REQUIRED、

        PROPAGATION_REQUIRES_NEW、

        PROPAGATION_SUPPORTS,共七种取值。

      隔离级别的取值必须以“ISOLATION_”开头,

        具体包括:

        ISOLATION_DEFAULT、

        ISOLATION_READ_COMMITTED、

        ISOLATION_READ_UNCOMMITTED、

        ISOLATION_REPEATABLE_READ、

        ISOLATION_SERIALIZABLE,共五种取值。

      如果事务是只读的,那么我们可以指定只读属性,

        使用“readOnly”指定。否则我们不需要设置该属性。

      超时属性的取值必须以“TIMEOUT_”开头,

        后面跟一个int类型的值,表示超时时间,单位是秒。

      不影响提交的异常是指,即使事务中抛出了这些类型的异常,

        事务任然正常提交。必须在每一个异常的名字前面加上“+”。

        异常的名字可以是类名的一部分。比如“+RuntimeException”、“+tion”等等。

      导致回滚的异常是指,当事务中抛出这些类型的异常时,事务将回滚。

        必须在每一个异常的名字前面加上“-”。异常的名字可以是类名的全部或者部分,

        比如“-RuntimeException”、“-tion”等等。

        

      以下是两个示例:

      

<property name="*Service">
          PROPAGATION_REQUIRED,ISOLATION_READ_COMMITTED,TIMEOUT_20,
          +AbcException,+DefException,-HijException
      </property>

 

 

      以上表达式表示,针对所有方法名以 Service 结尾的方法,

      使用 PROPAGATION_REQUIRED 事务传播行为,

      事务的隔离级别是 ISOLATION_READ_COMMITTED,

      超时时间为20秒,

      当事务抛出 AbcException 或者 DefException 类型的异常,则仍然提交,

      当抛出 HijException 类型的异常时必须回滚事务。

      这里没有指定"readOnly",表示事务不是只读的。

      

      

<property name="test">PROPAGATION_REQUIRED,readOnly</property>

 

 

      以上表达式表示,针对所有方法名为 test 的方法,

      使用 PROPAGATION_REQUIRED 事务传播行为,

      并且该事务是只读的。

      除此之外,其他的属性均使用默认值。

      比如,隔离级别和超时时间使用底层事务性资源的默认值,

      并且当发生未检查异常,则回滚事务,

      发生已检查异常则仍提交事务。

      

      参考:

      http://www.ibm.com/developerworks/cn/education/opensource/os-cn-spring-trans/section5.html

      

3.2  基于tx命名空间的方式来配置事务代理bean

      这种配置类似于AOP配置,只配置一个bean,

      当根据bean id使用getBean()获取bean实例时,Spring容器自动提供事务代理bean的实例.

      

      

<?xml version="1.0" encoding="UTF-8"?>
      <!-- 需要使用这样的beans头,指定tx,aop的schema -->  
      <beans xmlns="http://www.springframework.org/schema/beans"  
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
              xmlns:aop="http://www.springframework.org/schema/aop"
              xmlns:tx="http://www.springframework.org/schema/tx"
              xsi:schemaLocation="http://www.springframework.org/schema/beans  
                  http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                  http://www.springframework.org/schema/aop 
                  http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
                  http://www.springframework.org/schema/tx 
                  http://www.springframework.org/schema/tx/spring-tx-3.0.xsd" 
      > 
      
         <!-- 数据源使用JDBC数据源的局部事务,使用DataSourceTransactionManager类 -->
         <!-- DataSource配置,可配置为c3p0连接池等,这里省略 -->
         <bean id="dataSource" ...>...</bean>
         <bean id="transactionManager" 
               class="org.springframework.jdbc.datasouce.DataSouceTransactionManager">
           <!-- 配置DataSourceTransactionManager时,需要依赖注入DataSource的引用 -->
           <property name="dataSource" ref="dataSource"/>      
         </bean>
         
         <!-- 一个业务逻辑bean -->
         <bean id="newsDao" class="xxx.xxx.NewsDao" >
           <property name="ds" ref="newsDao" />
         </bean>
         
         <!-- 
              配置增强处理的bean(相当于切面类),也是Spring自动生成普通
              业务逻辑bean(targetBean)的代理Bean.里面的tx:method配置每个方法的事务属性,
              name配置方法名,可使用通配符.
         -->
         <tx:advice id="txAdvice" transaction-manager="transactionManager">
            <!-- 配置详细的事务语义 -->
            <tx:attributes>
              <!-- 表示get开头的方法是只读的 -->
              <tx:method name="get*" read-only="true" />
              <!-- 其他方法使用默认的事务设置,事务传播方式也可以默认么? -->
              <tx:method name="*" />
            </tx:attributes>
         </tx:advice>
         
         <!-- AOP元素配置 -->
         <aop:config>
           <!-- 配置一个切入点 xxx.xxx包下面所有已Imp1结尾的类的所有方法-->
           <aop:pointcut id="myPoint" 
                         expression="execution(* xxx.xxx.*Imp1.*(..))" />
           <!-- 配置 (事务代理)切入点(aop:pointcut) 和 切面类(tx:advice),将二者关联起来  -->
           <aop:advisor advice-ref="txAdvice" pointcut-ref="myPoint" />
         </aop:config>
      </beans>

 

      

      注:

        aop:config中 aop:pointcut配置切入点,表名哪些方法将会被事务代理增强.

        tx:advice 相当于配置一个切面类,并标明对符合条件的方法采用何种事务.

        aop:config中aop:advisor将上述二者关联起来

        

        <tx:attributes>的tx:method的

         name属性是必须的,可以使用通配符,表示与改事务语义管理的方法名.

         另外,还有属性:

         propagation,isolation,timeout,read-only,rollbak-for,no-rallback-for.(P684)

        

      附件中 classes12.jar是oracle的驱动包.

          

     

         

     

     

     

 

    

分享到:
评论

相关推荐

    spring声明式事务配置

    ### 标题解读:Spring声明式事务配置 Spring框架提供了两种主要类型的事务管理方式:编程式事务管理和声明式事务管理。声明式事务管理通过XML配置或注解的形式定义事务边界,使得业务逻辑与事务控制分离。 ### ...

    Spring声明式事务配置管理方法

    Spring声明式事务配置管理方法

    Spring使用XML配置声明式事务

    在Spring框架中,声明式事务管理是实现事务处理...在博文"Spring使用XML配置声明式事务"中,作者详细讲解了每个步骤,并可能通过示例代码展示了如何实际应用这些配置,帮助读者更好地理解和掌握Spring声明式事务管理。

    spring声明式事务管理配置方式

    在"spring声明式事务管理配置方式"中,主要涉及到以下几个关键知识点: 1. **Spring事务管理器(Transaction Manager)**: - Spring支持多种事务管理器,如DataSourceTransactionManager(用于JDBC事务)和...

    spring3,hibernate4 配置声明式事务管理(annotation方式)

    总的来说,Spring 3和Hibernate 4结合使用声明式事务管理,使得我们无需在代码中显式调用事务开始、提交和回滚,而是通过注解和配置文件来声明事务的边界和行为。这种方式降低了代码的复杂度,提高了可维护性和可...

    spring+mybatis的声明式事务

    在Spring中,声明式事务主要通过AOP(面向切面编程)实现,它允许我们在不修改业务代码的情况下,通过XML配置或Java配置,以及注解来控制事务的边界。 3. **XML配置事务** 在Spring的XML配置文件中,可以通过`...

    spring声明事务的配置

    以下是对Spring声明式事务配置的详细说明: 1. **Spring 1.x 声明事务方式** 在Spring 1.x中,声明式事务有两种主要的配置方式,第一种是通过XML配置逐个为每个业务类创建事务代理。首先,你需要声明一个事务管理...

    实验 spring 声明事务

    1. **配置Spring声明式事务**: 在Spring中,声明式事务管理依赖于AOP(面向切面编程)来实现。首先,需要配置一个事务管理器,通常使用`DataSourceTransactionManager`,它与数据源`dataSource`关联。然后,通过`...

    Spring源代码解析(六):Spring声明式事务处理.doc

    在 Spring 中,声明式事务处理可以通过配置 TransactionProxyFactoryBean 来实现。TransactionProxyFactoryBean 是一个 FactoryBean,它可以创建一个代理对象,该代理对象可以拦截业务方法的调用,并对事务进行管理...

    spring声明式事务处理demo

    在这个"spring声明式事务处理demo"中,我们将探讨如何在MyEclipse环境下实现这一功能。 首先,我们要理解Spring事务管理的两种主要方式:编程式事务管理和声明式事务管理。编程式事务管理通常通过AOP(面向切面编程...

    Spring中的四种声明式事务的配置

    在Spring框架中,声明式事务管理是通过AOP(面向切面编程)实现的,它允许开发者无需在业务代码中显式处理事务,而是通过配置来控制事务的边界。Spring提供了四种不同的方式来配置声明式事务,这使得事务管理更加...

    Spring声明式事务处理

    文件名为`Spring声明式事务处理-1.mht`到`Spring声明式事务处理-5.mht`,通过阅读这些文件,你将能够深入理解Spring声明式事务处理的各个方面,包括配置、使用场景、最佳实践以及常见问题的解决方法。

    Spring_Hibernate使用TransactionInterceptor声明式事务配置.doc

    Spring_Hibernate使用TransactionInterceptor声明式事务配置 在这篇文章中,我们将探讨使用Spring_Hibernate框架实现声明式事务配置的方法,具体来说,就是使用TransactionInterceptor来管理事务。在Spring框架中,...

    spring事务配置的五种方式

    其中,声明式事务因其简单易用而被广泛采用。本文将详细介绍Spring中事务配置的五种方式,帮助开发者更好地理解和运用这些配置方法。 #### 二、Spring事务配置的基本组成部分 Spring事务配置主要包含以下三个核心...

    Hibernate编程式事务与Spring Aop的声明式事务(spring与hibernate集成)

    本主题将深入探讨Hibernate的编程式事务管理和Spring AOP的声明式事务管理,以及两者如何在实际项目中集成使用。 **Hibernate编程式事务管理** Hibernate作为流行的ORM(对象关系映射)框架,提供了对JDBC事务的...

    Xml文件配置实现声明式事务管理

    在Spring框架中,声明式事务管理是一种非常重要的特性,它允许开发者通过XML配置或注解来定义事务的边界,而无需在业务代码中显式地管理事务。这种方式极大地提高了代码的可读性和可维护性。本篇文章将深入探讨如何...

Global site tag (gtag.js) - Google Analytics