本系列博客汇总在这里:Spring 汇总
事务控制
源码工程文件为:spring3.2_10 & spring3.2_11 & spring3.2_12 & spring3.2_13
一、什么是事务
一荣俱荣,一损俱损,很多复杂的操作我们可以把它看成是一个整体,要么同时成功,要么同时失败。
事务的四个特征ACID
- 原子性(Atomic):表示组成一个事务的多个数据库的操作的不可分割的单元,只有所有的操作成功才算成功,整个事务提交,其中任何一个操作失败了都是导致整个所有操作失败,事务会回滚。
- 一致性(Consistentcy):事务操作成功后,数据库所处的状态和业务规则一致。如果A账户给B账户汇 100,A 账户减去 100,B 加上 100,两个账户的总额是不变的。
- 隔离性(islation):在多个数据库的操作相同的数据并发时,不同的事务有自己的数据空间,事务与事务之间不受干扰(不是绝对的)。干扰程度受数据库或者操作事务的隔离级别来决定,隔离级别越高,干扰就越低,数据的一致性越好,并发性就越差。
- 持久性(Druability):一旦事务提交成功,数据就被持久化到数据库,不可以回滚。
二、Spring 使用注解对事务的控制
1、来处理事务传播特性
第一步
配置事务管理器
<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-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
<!-- Spring读取属性文件配置 -->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 数据源配置 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${driverClassName}"></property>
<property name="url" value="${url}"></property>
<property name="username" value="${uname}"></property>
<property name="password" value="${pword}"></property>
<!-- 初始化的连接数 -->
<property name="initialSize" value="${initialSize}"></property>
<!-- 连接池的最大连接数-->
<property name="maxActive" value="${maxActive}"></property>
<!-- 最大的空闲的连接数 -->
<property name="maxIdle" value="${maxIdle}"></property>
<!-- 最小的空闲连接数 -->
<property name="minIdle" value="${minIdle}"></property>
</bean>
<bean id="userDao" class="com.wyx.spring.dao.impl.OrderDaoImpl">
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean id="detailDao" class="com.wyx.spring.dao.impl.DetailDaoImpl">
<property name="dataSource" ref="dataSource"></property>
</bean>
<bean id="userService" class="com.wyx.spring.service.impl.OrderServiceImpl">
<property name="userDao" ref="userDao"></property>
</bean>
<!-- 定义事务的管理器 -->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 事务管理器的主键驱动 -->
<tx:annotation-driven transaction-manager="txManager"/>
</beans>
第二步
通过 @Transactional 来标注要使用事务的类或接口或方法,在项目中我们通常都会把事务开启在Service 层,建议把注解标注在接口的实现类或者是方法上。
- 注意:在 Service 层开启事务的时候,默认情况下,发生运行时异常会回滚,非运行时异常不会回滚。
可以设置对指定的异常回滚
- rollbackFor 或 rollbackForClassName 设置对哪些回滚。
- noRollbackFor 或 noRollbackForClassName 设置对哪些不回滚。
- @Transactional 的默认传播特性是 reqired,实际项目中 80% 都是采用 reqired。
事务的传播特性
-
REQUIRED:默认的传播特性,业务方法需要在一个事务中运行,如果一个方法已经处在一个事务中那么就加入到这个事务中,否则就会创建一个事务。
-
NEVER:指定的业务方法绝对不能在事务范围内运行,如果业务方法在某个事务中执行,就会抛异常,只有业务方法没有任何事务才正常执行。
被嵌套的事务
在事务中运行 -
MANDATORY:该属性指定业务方法只能在一个已经存在的事务中执行,业务方法不能自己发起自己的事务,如果业务方法不存在事务,容器就抛异常。
MANDATORY 完全和 NEVER 相反
如果没有在事务中运行
在有事务的环境中 -
SUPPORTS:如果业务方法中已经在某个事务中被调用,则方法就称为事务的一部分,如果外部业务方法没有开启事务,supports 该方法也会在没有事务的环境中执行。
在没有事务的环境下运行
在有事务的环境下运行 -
NOT_SUPPORTED:如果该业务方法在一个事务中被调用,那么当前的事务会被挂起,执行该业务方法,方法执行完毕唤醒被挂起的事务,如果业务方法不在一个事务中执行,该方法也不会开事务。不管是否在有无事务的环境中执行都不开启事务。
不在事务中运行
在事务中运行 -
REQUIRES_NEW:不管是否存在事务,业务方法总会自己开启一个事务,如果在已有事务的环境中调用,已有事务会被挂起,新的事务会被创建,直到业务方法调用结束,已有事务才被唤醒。
不在事务中调用
在事务中调用
注意:内外事务不受影响 -
NESTED:如果业务方法在一个事务中执行,就在这个事务中嵌套,如果没有事务按着 required 执行,开启单独的事务,这种事务有多个事务的保存点,内部事务的回滚对外部事务没有影响。
在没有事务中执行
在已有事务中执行
在已有事务总 Nested 事务发生异常
Nested 事务正常,已有事务异常
2、事务的并发
并发问题
脏读(dirty read)
A 事务读到 B 事务没有提交的数据,并且 A 来修改这个数据,如果恰巧 B 做事务回滚,那么 A 事务读到的数据就是错误的
不可重复读(unrepeatable read)
指的是 A 事务读取了 B 事务已经提交了的更改数据,假设 A 取款的过程中 B 向账户汇入 100,A 事务两次读取数据不一致。
幻读(phantom read)
A 事务读取 B 事务新增的数据,假设银行做在一个 A 事务中统计,在统计过程中 B 新增了用户,A 的事务中两次统计不同
第一类更新丢失
第二类更新丢失
3、事务的隔离级别
Sql92 标准提供 4 个隔离级别,会给我们自动根据不同事务的隔离级别加不同的锁
数据库的隔离级别越高,并发性就越差,性能就越低。
三、使用配置文件对事务控制
略
如有错误,欢迎指正!
来源:CSDN
作者:魏宇轩
链接:https://blog.csdn.net/qq_36260974/article/details/104116125