• spring事务配置详解


    一.前言

        好几天没有在对spring进行学习了,由于这几天在赶项目,没有什么时间闲下来继续学习,导致spring核心架构详解没有继续下去,在接下来的时间里面,会继续对spring的核心架构在继续进行学习;今天记录一下spring的事务配置,由于前几天在开发中遇到了spring的事务配置问题,很久没有对spring的事务进行配置了,导致有一些配置会说明忘了,这一篇博文在记录说明一下spring的事务,重新学习一下。

    二.spring的事务说明

       

       事务分为:编程性事务、声明式事务,在spring中常用了声明式事务来进行事务的配置,编程性事务的主要特点是:比较灵活,但是可扩展性不强;Spring声明式事务让我们从复杂的事务处理中得到解脱。使得我们再也无需要去处理获得连接、关闭连接、事务提交和回滚等这些操作。再也无需要我们在与事务相关的方法中处理大量的try…catch…finally代码。    

       Spring声明式事务时,有一个非常重要的概念就是事务属性。事务属性通常由事务的传播行为,事务的隔离级别,事务的超时值和事务只读标志组成。我们在进行事务划分时,需要进行事务定义,也就是配置事务的属性。 

       Spring在TransactionDefinition接口中定义这些属性,以供PlatfromTransactionManager使用, PlatfromTransactionManager是spring事务管理的核心接口。 

    TransactionDefinition  
    public interface TransactionDefinition {  
        int getPropagationBehavior();  
        int getIsolationLevel();  
        int getTimeout();  
        boolean isReadOnly();  
    }  
    

     getTimeout()方法,它返回事务必须在多少秒内完成。 

    isReadOnly(),事务是否只读,事务管理器能够根据这个返回值进行优化,确保事务是只读的。 
    getIsolationLevel()方法返回事务的隔离级别,事务管理器根据它来控制另外一个事务可以看到本事务内的哪些数据。

    三.概念说明

        脏读:在一个事务1读取了事务2中未提交的数据  然而事务2由于某种原因回滚了事务 。那么事务1读取的数据就是脏数据。

       不可重读(Unrepeatable Read):一个事务两次读同一行数据,可是这两次读到的数据不一样,就叫不可重读。如果一个事务在提交数据之前,另一个事务可以修改和删除这些数据,就会发生不可重读。

        幻读(Phantom Read):一个事务执行了两次查询,发现第二次查询结果比第一次查询多出了一行,这可能是因为另一个事务在这两次查询之间插入了新行。

    四.TransactionDefinition接口中定义了五个不同的事务隔离级别 

        ISOLATION_DEFAULT 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别。

    *另外四个与JDBC的隔离级别相对应 
            1.ISOLATION_READ_UNCOMMITTED  

                这是事务最低的隔离级别,它充许别外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读。

           2.ISOLATION_READ_COMMITTED  

               保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。这种事务隔离级别可以避免脏读出现,但是可能会出现不可重复读和幻像读。 

           3.ISOLATION_REPEATABLE_READ 

               这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)。 

           4.ISOLATION_SERIALIZABLE  

              这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读外,还避免了幻像读。

    五.事务的传播特性

    在TransactionDefinition接口中定义了七个事务传播行为。 

      1.PROPAGATION_REQUIRED

         如果存在一个事务,则支持当前事务。如果没有事务则开启一个新的事务。

      2.PROPAGATION_SUPPORTS

         如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行。但是对于事务同步的事务管理器,PROPAGATION_SUPPORTS与不使用事务有少许不同。

      3.PROPAGATION_MANDATORY 

         如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常。 

      4.PROPAGATION_REQUIRES_NEW 

         总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起。 

      5.PROPAGATION_NOT_SUPPORTED 

         总是非事务地执行,并挂起任何存在的事务。 

      6.PROPAGATION_NEVER

         总是非事务地执行,如果存在一个活动事务,则抛出异常 

      7.PROPAGATION_NESTED

        如果一个活动的事务存在,则运行在一个嵌套的事务中. 如果没有活动事务, 则按TransactionDefinition.PROPAGATION_REQUIRED 属性执行这是一个嵌套事务,使用JDBC 3.0驱动时,仅仅支持DataSourceTransactionManager作为事务管理器。需要JDBC 驱动的java.sql.Savepoint类。有一些JTA的事务管理器实现可能也提供了同样的功能。 使用PROPAGATION_NESTED,还需要把PlatformTransactionManager的nestedTransactionAllowed属性设为true; 而nestedTransactionAllowed属性值默认为false; 

     六.spring事务配置的五种方式

       1.说明:

          Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource、TransactionManager和代理机制这三部分,无论哪种配置方式,一般变化的只是代理机制这部分。

          DataSource、TransactionManager这两部分只是会根据数据访问方式有所变化,比如使用Hibernate进行数据访问时,DataSource实际为SessionFactory,TransactionManager的实现为HibernateTransactionManager。

       2.根据代理机制的不同,总结了五种Spring事务的配置方式,配置文件如下:

     第一种方式:每个Bean都有一个代理

    <?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:context="http://www.springframework.org/schema/context"  
        xmlns:aop="http://www.springframework.org/schema/aop"  
        xsi:schemaLocation="http://www.springframework.org/schema/beans   
               http://www.springframework.org/schema/beans/spring-beans-2.5.xsd  
               http://www.springframework.org/schema/context  
               http://www.springframework.org/schema/context/spring-context-2.5.xsd  
               http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">  
      
        <bean id="sessionFactory"    
                class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">    
            <property name="configLocation" value="classpath:hibernate.cfg.xml" />    
            <property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" />  
        </bean>    
      
        <!-- 定义事务管理器(声明式的事务) -->    
        <bean id="transactionManager"  
            class="org.springframework.orm.hibernate3.HibernateTransactionManager">  
            <property name="sessionFactory" ref="sessionFactory" />  
        </bean>  
          
        <!-- 配置DAO -->  
        <bean id="userDaoTarget" class="com.bluesky.spring.dao.UserDaoImpl">  
            <property name="sessionFactory" ref="sessionFactory" />  
        </bean>  
          
        <bean id="userDao"    
            class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">    
               <!-- 配置事务管理器 -->    
               <property name="transactionManager" ref="transactionManager" />       
            <property name="target" ref="userDaoTarget" />    
             <property name="proxyInterfaces" value="com.bluesky.spring.dao.GeneratorDao" />  
            <!-- 配置事务属性 -->    
            <property name="transactionAttributes">    
                <props>    
                    <prop key="*">PROPAGATION_REQUIRED</prop>  
                </props>    
            </property>    
        </bean>    
    </beans>  
    

     第二种方式:所有Bean共享一个代理基类

    <?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:context="http://www.springframework.org/schema/context"  
        xmlns:aop="http://www.springframework.org/schema/aop"  
        xsi:schemaLocation="http://www.springframework.org/schema/beans   
               http://www.springframework.org/schema/beans/spring-beans-2.5.xsd  
               http://www.springframework.org/schema/context  
               http://www.springframework.org/schema/context/spring-context-2.5.xsd  
               http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">  
      
        <bean id="sessionFactory"    
                class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">    
            <property name="configLocation" value="classpath:hibernate.cfg.xml" />    
            <property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" />  
        </bean>    
      
        <!-- 定义事务管理器(声明式的事务) -->    
        <bean id="transactionManager"  
            class="org.springframework.orm.hibernate3.HibernateTransactionManager">  
            <property name="sessionFactory" ref="sessionFactory" />  
        </bean>  
          
        <bean id="transactionBase"    
                class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"    
                lazy-init="true" abstract="true">    
            <!-- 配置事务管理器 -->    
            <property name="transactionManager" ref="transactionManager" />    
            <!-- 配置事务属性 -->    
            <property name="transactionAttributes">    
                <props>    
                    <prop key="*">PROPAGATION_REQUIRED</prop>    
                </props>    
            </property>    
        </bean>      
         
        <!-- 配置DAO -->  
        <bean id="userDaoTarget" class="com.bluesky.spring.dao.UserDaoImpl">  
            <property name="sessionFactory" ref="sessionFactory" />  
        </bean>  
          
        <bean id="userDao" parent="transactionBase" >    
            <property name="target" ref="userDaoTarget" />     
        </bean>  
    </beans>  
    

    第三种方式:使用拦截器  

    <?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:context="http://www.springframework.org/schema/context"  
        xmlns:aop="http://www.springframework.org/schema/aop"  
        xsi:schemaLocation="http://www.springframework.org/schema/beans   
               http://www.springframework.org/schema/beans/spring-beans-2.5.xsd  
               http://www.springframework.org/schema/context  
               http://www.springframework.org/schema/context/spring-context-2.5.xsd  
               http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">  
      
        <bean id="sessionFactory"    
                class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">    
            <property name="configLocation" value="classpath:hibernate.cfg.xml" />    
            <property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" />  
        </bean>    
      
        <!-- 定义事务管理器(声明式的事务) -->    
        <bean id="transactionManager"  
            class="org.springframework.orm.hibernate3.HibernateTransactionManager">  
            <property name="sessionFactory" ref="sessionFactory" />  
        </bean>   
         
        <bean id="transactionInterceptor"    
            class="org.springframework.transaction.interceptor.TransactionInterceptor">    
            <property name="transactionManager" ref="transactionManager" />    
            <!-- 配置事务属性 -->    
            <property name="transactionAttributes">    
                <props>    
                    <prop key="*">PROPAGATION_REQUIRED</prop>    
                </props>    
            </property>    
        </bean>  
            
        <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">    
            <property name="beanNames">    
                <list>    
                    <value>*Dao</value>  
                </list>    
            </property>    
            <property name="interceptorNames">    
                <list>    
                    <value>transactionInterceptor</value>    
                </list>    
            </property>    
        </bean>    
        
        <!-- 配置DAO -->  
        <bean id="userDao" class="com.bluesky.spring.dao.UserDaoImpl">  
            <property name="sessionFactory" ref="sessionFactory" />  
        </bean>  
    </beans>  
    

    第四种方式:使用tx标签配置的拦截器

    <?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:context="http://www.springframework.org/schema/context"  
        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-2.5.xsd  
               http://www.springframework.org/schema/context  
               http://www.springframework.org/schema/context/spring-context-2.5.xsd  
               http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd  
               http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">  
      
        <context:annotation-config />  
        <context:component-scan base-package="com.bluesky" />  
      
        <bean id="sessionFactory"    
                class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">    
            <property name="configLocation" value="classpath:hibernate.cfg.xml" />    
            <property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" />  
        </bean>    
      
        <!-- 定义事务管理器(声明式的事务) -->    
        <bean id="transactionManager"  
            class="org.springframework.orm.hibernate3.HibernateTransactionManager">  
            <property name="sessionFactory" ref="sessionFactory" />  
        </bean>  
      
      <!-- 配置事务的传播特性  -->   
        <tx:advice id="txAdvice" transaction-manager="transactionManager">  
            <tx:attributes>  
                <tx:method name="save*" propagation="REQUIRED" />  
      
        <tx:method name="update*" propagation="REQUIRED" />  
      
        <tx:method name="delete*" propagation="REQUIRED" />  
      
        <tx:method name="*" read-only="true" />  
            </tx:attributes>  
        </tx:advice>  
        <!-- 哪些类的哪些方法参与事务 -->   
        <aop:config>  
            <aop:pointcut id="interceptorPointCuts"  
                expression="execution(* com.bluesky.spring.dao.*.*(..))" />  
            <aop:advisor advice-ref="txAdvice"  
                pointcut-ref="interceptorPointCuts" />          
        </aop:config>        
    </beans>  
    

    第五种方式:全注解 

    <?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:context="http://www.springframework.org/schema/context"  
        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-2.5.xsd  
               http://www.springframework.org/schema/context  
               http://www.springframework.org/schema/context/spring-context-2.5.xsd  
               http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd  
               http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">  
      
        <context:annotation-config />  
        <context:component-scan base-package="com.bluesky" />  
      
        <tx:annotation-driven transaction-manager="transactionManager"/>  
      
        <bean id="sessionFactory"    
                class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">    
            <property name="configLocation" value="classpath:hibernate.cfg.xml" />    
            <property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" />  
        </bean>    
      
        <!-- 定义事务管理器(声明式的事务) -->    
        <bean id="transactionManager"  
            class="org.springframework.orm.hibernate3.HibernateTransactionManager">  
            <property name="sessionFactory" ref="sessionFactory" />  
        </bean>  
          
    </beans>  
    

    此时在DAO上需加上@Transactional注解,如下

    package com.bluesky.spring.dao;  
      
    import java.util.List;  
      
    import org.hibernate.SessionFactory;  
    import org.springframework.beans.factory.annotation.Autowired;  
    import org.springframework.orm.hibernate3.support.HibernateDaoSupport;  
    import org.springframework.stereotype.Component;  
      
    import com.bluesky.spring.domain.User;  
      
    @Transactional  
    @Component("userDao")  
    public class UserDaoImpl extends HibernateDaoSupport implements UserDao {  
      
        public List<User> listUsers() {  
            return this.getSession().createQuery("from User").list();  
        }  
          
          
    }  
  • 相关阅读:
    NSURLConnection与NSURLSession的区别
    微信支付流程
    支付宝支付流程
    配置openfire问题(Oracle)
    id和instancetype
    数组和集合
    静态变量,静态常量以及全局变量
    内存的那些事
    Block循环引用解析
    线程的几个小问题
  • 原文地址:https://www.cnblogs.com/hongwz/p/5485397.html
Copyright © 2020-2023  润新知