认识事务
- 可以把一系列(多条sql语句)要执行的操作称为事务,而事务管理就是管理这些操作要么完全执行,要么完全不执行(很经典的一个例子是:A要给B转钱,首先A的钱减少了,但是突然的数据库断电了,导致无法给B加钱,然后由于丢失数据,B不承认收到A的钱;在这里事务就是确保加钱和减钱两个都完全执行或完全不执行,如果加钱失败,那么不会发生减钱)。
事务管理的意义:
- 保证数据操作的完整性和安全性。
事务管理的四大特性: - 记住 - ACID
- 原子性:事务的整个操作是一个整体,不可以分割,要么全部成功,要么全部失败。
- 一致性:事务操作的前后,数据表中的数据没有变化。
- 隔离性:事务操作是相互隔离不受影响的。
- 持久性:数据一旦提交,不可改变,永久的改变数据表数据。
事务管理操作:
- 开启事务管理:开启之后,下面的sql语句并不会马上执行并把结果写到表中,而是会写到事务日志中。
- start transaction;
- 回滚操作:会清掉开始事务管理之后写到事务日志中的内容,即恢复到开启事务管理之前。
- 语法:rollback; - 如果程序发生了异常,将数据恢复到没有操作之前的那个状态。
- 注意:回滚操作只是回退"写"的内容,对于普通的读表select语句不能回退。
- 事务提交:将sql语句的结果写到数据表中。
- 语法:commit: - 持久化的保存
- 当 commit 或 rollback 语句执行后,事务会自动关闭
Spring事务管理机制
- Spring事务管理 由三个接口共同完成 :
- lPlatformTransactionManager 平台相关事务管理器 - 事务管理器
- lTransactionDefinition 事务定义信息 (通过配置如何进行事务管理:隔离、传播、超时、只读)
- lTransactionStatus 事务状态 (事务管理过程中,每个时间点事务 状态信息 )
PlatformTransactionManager 事务管理器
- 提交事务 commit、回滚事务 rollback、 获取事务状态 getTransaction
- lDataSourceTransactionManager 针对 JdbcTemplate、MyBatis 事务控制 ,使用Connection进行事务控制
- 开启事务 conn.setAutoCommit(false);
- 提交事务 conn.commit();
- 回滚事务 conn.rollback();
- lHibernateTransactionManager 针对Hibernate框架进行事务管理, 使用Session的Transaction相关操作进行事务控制
- 开启事务 session.beginTransaction();
- 提交事务 session.getTransaction().commit();
- 回滚事务 session.getTransaction().rollback();
- 用户应该选择和使用持久层技术,对应的事务管理器
TransactionDefinition 事务定义信息
- 隔离级别获取 getIsolationLevel 、 传播行为获取 getPropagationBehavior 、 获取超时时间getTimeout 、isReadOnly 是否只读
事务的隔离级别
- 事务四大特性 ACID --- 隔离性引发问题 ---- 解决事务的隔离问题--隔离级别
- Mysql 默认隔离级别 REPEATABLE_READ
- Oracle 默认隔离级别 READ_COMMITTED
事务的传播行为
- 什么是事务的传播行为? 为什么需要 ?
- 事务传播行为用于解决两个被事务管理的方法互相调用问题
- REQUIRED、SUPPORTS、MANDATORY : 支持当前事务, A调用B,如果A事务存在,A和B处于同一个事务 (事务默认传播行为 REQUIRED )
- REQUIRES_NEW、NOT_SUPPORTED、NEVER : 不会支持原来的事务 ,A调用B, 如果A事务存在, B肯定不会和A处于同一个事务
- NESTED: 嵌套事务 ,只对DataSourceTransactionManager有效 ,底层使用JDBC的SavePoint机制,允许在同一个事务设置 保存点,回滚保存点
面试题:REQUIRED、REQUIRES_NEW、NESTED 区分
- REQUIRED 一个事务
- REQUIRES_NEW 两个事务
- NESTED 一个事务,事务可以设置保存点,回滚到保存点 ,选择提交或者回滚
TransactionStatus 事务状态
- 事务运行过程中,每个时间点 事务状态信息 !
- 事务的结束必须通过commit , rollback 作用标记为回滚
try { 操作 commit } catch (){ rollback }
三个对象之间的关系:
- 用户管理事务,需要先配置事务管理方案TransactionDefinition、 管理事务通过TransactionManager 完成,TransactionManager根据 TransactionDefinition进行事务管理,在事务运行过程中,每个时间点都可以通过获取TransactionStatus 了解事务运行状态!
Spring事务管理两种方式
- Spring支持两种事务管理: 编程式事务管理、 声明式事务管理 - 支持
- l编程式事务管理: 要修改原来的代码,加入事务管理代码 (侵入性 )--- 不推荐,不使用
- 实际中是通过TransactionTemplate 操作事务管理
template.execute(new TransactionCallbackWithoutResult(){ void doInTransactionWithoutResult(TransactionStatus status) { // 需要事务管理的代码 } });
- l声明式事务管理: 底层就是AOP的环绕通知, --- 推荐
声明式事务管理案例
编写转账案例,引出事务管理问题
- 第一步:建立数据表
- 第二步: 编写转账代码
- 第三步: 编写测试
XML配置方式添加事务管理(tx、aop约束)
第一步: 引入aop和tx 的名称空间,导入aop和tx 的jar
- <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.xsd
- http://www.springframework.org/schema/context
- http://www.springframework.org/schema/context/spring-context.xsd
- http://www.springframework.org/schema/aop
- http://www.springframework.org/schema/aop/spring-aop.xsd
- http://www.springframework.org/schema/tx
- http://www.springframework.org/schema/tx/spring-tx.xsd">
第二步: 配置 transactionManager(spring提供 Around 通知 )
- 根据不同的持久层框架,配置不同的事务管理器,事务管理器需要依赖数据源信息
第三步: 配置切入点和切面
- 在spring的配置文件中,使用<tx:advice>配置通知信息,其实就是哪些需要方法需要增强,事务管理也是aop的应用
<tx:advice> <tx:attributes> <tx:method name="具体的方法名"/> </tx:attributes> </tx:advice>
- 使用aop:config来配置切入点和切面信息
aop:pointcut 配置切入点, id=""起个名字,expression="" 配置切入点表达式 aop:advisor 配置切面,advice-ref="" pointcut-ref="" 将切入点和通知整合到一起
注解配合方式添加事务管理@Transactional
- 第一步: 配置注解驱动事务管理
- 第二步: 在需要管理事务的方法或者类上面 添加@Transactional 注解
小结
- 问题: XML配置方式和注解配置方式 进行事务管理 哪种用的多?
- XML方式 和注解都在使用
- 使用@Transactional注解进行事务管理,方便,不过配置太分散, 使用XML进行事务管理 属性集中配置,便于管理和维护