Spring的事务管理

事务原本是数据库中的概念,在 Dao 层。但一般情况下,需要将事务提升到业务层, 即 Service 层。这样做是为了能够使用事务的特性来管理具体的业务。

在 Spring 中通常可以通过以下两种方式来实现对事务的管理:

(1)使用 Spring 的事务注解管理事务

(2)使用 AspectJ 的 AOP 配置管理事务

一、配置spring事务

<?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:tx="http://www.springframework.org/schema/tx"
   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.xsd
      http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
      http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
      http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
   
   <!-- 启动aspectj注解的支持 -->
   <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
   <!-- spring声明式事务管理控制,配置事务管理器类(注册事务管理器,将其注入到spring容器中) -->
   <bean id="txManager"
      class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
      <!-- 事务管理器管理的数据源 -->
      <property name="dataSource" ref="dataSource" />
   </bean>
   <!-- 配置事务增强(如何管理事务,只读、读写...) -->
   <tx:advice id="txAdvice" transaction-manager="txManager">
      <tx:attributes>
         <!-- name="save*" :以save开头的方法 propagation:定义特定名称方法的事务传播行为 read-only="true":表示在这种方法中,一定不能出现修改数据库的操作。否则报异常 -->
         <tx:method name="save*" propagation="REQUIRED" />
         <tx:method name="insert*" propagation="REQUIRED" />
         <tx:method name="delete*" propagation="REQUIRED" />
         <tx:method name="update*" propagation="REQUIRED" />
         <tx:method name="find*" propagation="SUPPORTS" read-only="true" />
         <tx:method name="get*" propagation="SUPPORTS" read-only="true" />
         <tx:method name="select*" propagation="SUPPORTS" read-only="true" />
      </tx:attributes>
   </tx:advice>
   <!-- aop配置,拦截哪些方法(切入点表达式,拦截上面的事务增强) -->
   <aop:config>
      <aop:pointcut id="pt"
         expression="execution(* com.zsn.yqx.services.impl.*.*(..))" />
      <aop:advisor advice-ref="txAdvice" pointcut-ref="pt" />
   </aop:config>
</beans>

事务的重点说明

1、事务的四个关键属性(ACID)

  • 原子性(atomicity): 事务是一个原子操作,由一系列动作组成.事务的原子性确保动作要么全部完成要么完全不起作用.
  • 一致性(consistency): 一旦所有事务动作完成,事务就被提交.数据和资源就处于一种满足业务规则的一致性状态中.
  • **隔离性(isolation): **可能有许多事务会同时处理相同的数据,因此每个事物都应该与其他事务隔离开来,防止数据损坏.
  • 持久性(durability): 一旦事务完成,无论发生什么系统错误,它的结果都不应该受到影响.通常情况下,事务的结果被写到持久化存储器中.

2、事务传播属性

当事务方法被另一个事务方法调用时,必须指定事务应该如何传播.例如:方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行.
事务的传播行为可以由传播属性指定.Spring定义了7种类传播行为.

spring如何手动获取事务管理器 spring开启事务管理_spring如何手动获取事务管理器

常用的就两种:REQUIRED、SUPPORTS

3、事务的隔离级别

当同一个应用程序或者不同应用程序中的多个事务在同一个数据集上并发执行时,可能会出现许多意外的问题。
并发事务所导致的问题可以分为下面三种类型:

1、脏读:对于两个事务T1,T2,T1读取了已经被T2更新但还没有被提交的字段.之后,若T2回滚,T1读取的内容就是临时且无效的.
2、不可里复读(更新):入 进值就不同了.人之铅然后T2在该表中插之后,T1再次读取同一个字段,值就不同了.
3、幻读(增删):对于两个事务T1,T2,T1 从一个表中读取了一个字段,然后T2在该表中插入了一些新的行.之后,如果T1 再次读取同一个表,就会多出几行

spring如何手动获取事务管理器 spring开启事务管理_spring如何手动获取事务管理器_02

事务的隔离级别要得到底层数据库引擎的支持,而不是应用程序或者框架的支持.

  • Oracle支持的2种事务隔离级别:READ_COMMITED(默认隔离级别),SERIALIZABLE
  • Mysql支持4中事务隔离级别,mysql默认事务隔离级别为:REPEATABLE-READ