Spring中管理数据库事务的配置使用详解

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring中管理数据库事务的配置使用详解相关的知识,希望对你有一定的参考价值。

参考技术A 配置Service层中的哪些方法需要使用到事务,一般开发使用组的形式,即如下

表示该方法配置的事务

表示该类下所有的方法都是用该事务(与方法不冲突)

Spring-事务配置和详解

一、Spring事务配置

  在项目开发过程中经常会使用事务来确保数据的一致性。根据网上的资料整理一下在spring中配置事务的几种方式。无论是哪种方式都需要在配置文件中配置连接池和事务管理器,代码如下。

<!-- 读取配置文件 -->
<bean
     class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
     <property name="locations">
         <list>
             <value>classpath:database.properties</value>
             <value>classpath:service.properties</value>
         </list>
     </property>
     <property name="fileEncoding" value="UTF-8" />
     <property name="ignoreResourceNotFound" value="false" />
</bean>
<!--连接池 -->
<bean id="dataSource"
     class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="${db.driver}" />
    <property name="url" value="${db.url}" />
    <property name="username" value="${db.username}" />
    <property name="password" value="${db.password}" />
</bean>
<!-- 配置事务管理器 -->
<bean id="transactionManager"
     class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
</bean>

 

  1、声明式事务管理

  1.1 基于AspectJ的XML方式的配置 这是我觉得最好的方式,基于aop配置,当新增的方法要使用事务管理时,无需修改代码。首先在配置文件xml中引入aop和tx的命名空间

  

xmlns:tx="http://www.springframework.org/schema/tx" 
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop   
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"

   1.2 然后在xml中加入aop的配置。下面的配置就是在services的切入点上应用txAdvice的增强,services的切入点就是ymy.com.service.impl包下的所有方法应用txAdvice的增强。然后txAdvice是在所有以create,add,delete,update,change开头的方法上加上事务管理。

<!-- 定义事务通知 (事务的增强)-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <!-- 定义方法的过滤规则 -->
    <tx:attributes>
        <!-- 所有方法都使用事务 -->
        <!-- 
            propagation:事务传播行为
            isolation:事务隔离
            read-only:只读
            rollback-for:发生哪些异常回滚
            no-rollback-for:发生哪些异常不回滚 
            timeout:过期信息    
         -->
        <tx:method name="create*" propagation="REQUIRED"/>
        <tx:method name="add*" propagation="REQUIRED"/>
        <tx:method name="delete*" propagation="REQUIRED"/>
        <tx:method name="update*" propagation="REQUIRED"/>
        <tx:method name="change*" propagation="REQUIRED"/>
    </tx:attributes>
</tx:advice>
<!-- 定义AOP配置 配置切面 -->
<aop:config>
    <!-- 定义一个切入点 -->
    <aop:pointcut id="services" expression="execution (* ymy.com.service.impl.*.*(..))" />
    <!-- 对切入点和事务的通知,进行适配 -->
    <aop:advisor advice-ref="txAdvice" pointcut-ref="services"/>
</aop:config>

 

   采用这种方式配置,当方法是按照事务定义的规则命名时,都会加入事务管理。

  2、基于注解事务管理

  这种方式是我觉得最简单的,第二推荐。要采用注解的方式,需要在配置文件中开启注解事务。

<!-- 开启注解事务 -->
<tx:annotation-driven transaction-manager="transactionManager"/>

 

  在使用时只需在对应的类上添加注解@Transactional即可

@Service
@Transactional(propagation=Propagation.REQUIRED)
) public class TaskService implements ITaskService { }

二、Spring事务详解

  1、数据库事务的隔离级别有四个

  Read uncommitted(读未提交)、
  Read committed(读已提交)、
  Repeatable read(重复读) MySQL数据库默认的隔离级别
  Serializable(序列化) ORACLE数据库默认的隔离级别
  这四个级别可以逐个解决脏读、不可重复读、幻读这几类问题。
  脏读:脏读是指在一个事务处理过程里读取了另一个未提交的事务中的数据
  不可重复读:是指某个数据,在一个事务下多次查询,查询出了不同的结果。这是因为在查询间隔被另一个事务修改了
  例如事务T1查询了一个数据,事务T2修改了数据,T1又查询了一次,结果跟第一次的不同,就发生了不可重复度
  幻读:幻读是事务非独立执行时发生的一种现象。例如事务T1对一个表中所有的行的某个数据项做了从“1”修改为“2”的操作,这时事务T2又对这个表中插入了一行数据项,而这个数据项的数值还是为“1”并且提交给数据库。而操作事务T1的用户如果再查看刚刚修改的数据,会发现还有一行没有修改,其实这行是从事务T2中添加的,就好像产生幻觉一样,这就是发生了幻读。
                                                  √: 可能出现    ×: 不会出现
                              技术分享图片

  2、Spring事务有7种传播行为

                              技术分享图片

 

  3、Spring事务的隔离级别

                              技术分享图片

  4、Spring事务回滚的注意点

    4.1 原理和概念:@Transaction是基于动态代理机制
    a. @Transaction应用在接口、接口方法、类、类中的public方法 上面的
    b. @Transaction只能应用在public定义的方法上面,如果使用在protected或者private的方法上面,就不会产生事务的效果
    c. 建议将@Transaction声明在类或者类中的方法上面,不要声明在接口和接口的方法上面。在接口上使用 @Transactional 注解,只能当你设置了基于接口的代理时它才生效
    d. 一个类中一个A方法调用有事务的B方法,事务是不会起作用的。
    e. 默认spring事务只在发生未被捕获的 runtimeexcetpion时才回滚
    这种情况不会回滚
    技术分享图片
    
    这两种种情况会回滚
    技术分享图片
    技术分享图片
 


以上是关于Spring中管理数据库事务的配置使用详解的主要内容,如果未能解决你的问题,请参考以下文章

Spring事务管理那些事

解读底层原理,分析Spring事务管理那些事

Spring声明式事务管理与配置详解

Spring事务管理(详解+实例)

Spring事务管理(详解+实例)

Spring事务管理(详解+实例)