Spring学习笔记五:Spring进行事务管理

转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6776256.html 

     事务管理主要负责对持久化方法进行统一的提交或回滚,Spring进行事务管理即我们无需在代码中显式地书写事务的开启、提交、回滚等操作了,我们只需为Spring指明有哪些方法需要进行事务管理,Spring自动在运行时为那些方法进行事务管理。使用Spring进行事务管理的工作就在于,配置好事务管理器,以及在哪些方法进行管理即可

一:Spring底层关于事务管理的API

    Spring封装了几个API用于管理事务,无论在后面使用哪种事务声明方式,底层都是调用这几个API工作的。了解这些API,对于后面配置事务时要配置哪些标签项就一清二楚了。其中,最重要的是前两个:事务管理器、事务定义信息配置接口

    1:事务管理器:对事务进行配置,比如:哪些方法进行事务管理、回滚信息配置等。在DAO层使用不同的持久层框架时,所用的事务管理器是不同的。在配置时,要根据所用的持久层框架来配置事务管理器,即:配置真正进行事务管理的实现类。主要有以下几种:其中,前两种是常用的。

    2:事务定义:主要对事务传播属性、隔离级别、超时时间、是否只读进行配置。

    1)事务传播属性:确定如何为持久化方法增加事务行为。主要解决Service层中业务方法的相互调用问题

    事务传播传播属性是针对 当前将要执行的持久化操作方法 所面临的7种情况下 作如何反应,主要分为三种:

    第一种,“加入当前事务,将执行的方法有三种选择:

   PROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务。
   PROPAGATION_SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行。
   PROPAGATION_MANDATORY--支持当前事务,如果当前没有事务,就抛出异常。

   (上面三种配置的意思是:假设业务方法A中调用了方法B,如果当前有事务(即方法A开启了事务),就把方法B加入当前事务中被管理。如果当前没有事务在执行,则三种配置分别对应了三种行为:新建一个事务来管理方法B、不进行事务管理直接运行方法B、抛出异常)

    第二种,“不使用当前事务”:
    PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起不用。

    (即:假设业务方法A中调用了方法B,自己新建一个事务来管理将要执行的持久化方法B,如果当前所处的方法A中已有事务,那就挂起当前事务。)
    PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务,就把当前事务挂起不用。

    (即:假设业务方法A中调用了方法B,则方法B不进行事务管理,如果方法A已有事务,则把A的事务挂起。)
    PROPAGATION_NEVER--以非事务方式执行,如果当前所处方法中存在事务,则抛出异常。

    (即:假设业务方法A中调用了方法B,则持久化方法B不进行事务管理,如果A已有事务,则抛出异常)

    第三种,“嵌套事务”:

    PROPAGATION_NESTED -- 总是新建一个事务来执行持久化方法。如果方法所处位置已有事务了,就形成了嵌套事务。

    (事务传播属性分三类,其中常用的就是三类中的第一个情况)

    2)隔离级别配置:隔离级别是为了解决并发事务可能引发脏读、不可重复读、幻读的情况而配置的

   1. ISOLATION_DEFAULT: 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别,即:把隔离性交给数据库来保证。

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

   3. ISOLATION_READ_COMMITTED: 保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。可以防止脏读。

   4. ISOLATION_REPEATABLE_READ: 这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。

   5. ISOLATION_SERIALIZABLE 这是花费最高代价但是最可靠的事务隔离级别。事务被处理为串行执行。可防止脏读,不可重复读,幻像读。

    

    3)只读属性:如果把事务定义为只读,则该事务中不能进行修改类数据库操作,如:insert/update/delete等。只能进行查询操作

    4)超时时间:事务的存在时间,一般很少用到。

    

二:Spring事务管理的准备

    在Spring中进行事务管理,无论哪种方式,都需要使用连接池。连接池我们一般使用C3P0来进行优化。

   首先,在一个properties文件中配置好c3p0的配置信息,如:驱动、数据库url、账户、密码等。

   然后,在applicationContext.xml中注册连接池,选择C3P0的ComboPooledDataSourse,配置好id以及一系列属性:

     默认的数据源配置:

三:Spring声明式事务管理——基于AspectJ的XML配置,使用AOP思想

    1:首先,配置事务管理器,根据持久层框架来选择。如:使用Spring提供的JDBCTemplate框架进行持久化操作,则事务管理器为DataSourseTransactionManager。配置时,需要把dataSourse注入给事务管理器。

    <!-- 事务管理器(PlatformTransactionManager) -->
    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    2:然后配置通知:AspectJ提供了基于AOP的事务管理的通知,标签是<tx:advice>。

    需要配置:通知的id、所用到的事务管理器id、<tx:attributes>子标签

           <tx:attributes>子标签内:配置需要事务管理的方法们

           切入点<tx:method name="需要进行事务管理的方法名可以用正则表达式"  对该方法进行事务定义,包括:事务隔离级别属性、事务传播属性、只读属性、回滚异常和不回滚异常配置等>

   <!-- 事务通知 -->
    <tx:advice id="txAdvice" transaction-manager="txManager">
        <!-- 为哪些方法进行事务管理、怎么管理-->
        <tx:attributes>
            <!-- 所有get开头的方法的事务定义 -->
            <tx:method name="get*" propagation="REQUIRED"/>//以正则表达式的形式匹配需要进行事务管理的方法,并指明如何管理事务
            <!-- 其他的方法的事务定义-->
            <tx:method name="*" .../>
        </tx:attributes>
    </tx:advice>

    3:配置切面

    上面配置了的事务通知,通过  正则表达式或精确的方法名 为方法制定了相应的事务。接下来,就要通过切面,把  事务通知  切入到具体的需要事务管理的类中去。

    事务通知中定义的method与切面中定义的切入点是怎么匹配的呢?这个过程发生了两次匹配:首先,pointcut表达式根据“返回值 路径.方法名.(参数列表)” 匹配筛选出了一堆持久化操作的方法;然后tx:advice再对这些方法进行匹配筛选:符合 name属性格式的方法名的持久化方法就进行name所处tx:method标签内定义的事务管理。

    <aop:config>
      <aop:pointcut id="pointcut1" expression="execution(返回值 路径.方法名.(参数列表))"/>//切入点筛选出需要进行事务管理的方法,至于如何管理,则在tx:advice中再匹配
      <aop:pointcut id="pointcut2" expression="execution(返回值 路径.方法名.(参数列表))"/>
      <aop:pointcut id="pointcut3" expression="execution(返回值 路径.方法名.(参数列表))"/>
        <aop:advisor advice-ref="txAdvice1" pointcut-ref="pointcut1"/>
        <aop:advisor advice-ref="txAdvice2" pointcut-ref="pointcut2"/>
        <aop:advisor advice-ref="txAdvice3" pointcut-ref="pointcut3"/>
    </aop:config>

    总结:基于AspectJ的XML事务管理的使用过程为:

   配置数据源——配置事务管理器——配置事务管理通知为不同名称格式的方法们自定义事务——配置切面把事务管理通知切入到需要事务管理的方法们

原文地址:https://www.cnblogs.com/ygj0930/p/6776256.html