typora-root-url: ./img

事务
  • 原子性
  • 一致性
  • 隔离性
  • 持久性

编程式事务:
  1. TransactionFilter{
  2. try{
  3. //获取链接
  4. //设置非自动提交
  5. chain.doFilter();
  6. //成功之后提交
  7. }catch(Exception e){
  8. //回滚
  9. }finally{
  10. //关闭连接释放资源
  11. }
  12. }

声明式事务:

以前通过复杂的编程来编写一个事务, 替换为只需要告诉Spring哪个方法是事务方法即可; Spring自动进行事务控制, 类似AOP环绕通知
事务管理代码的固定模式作为一种横切关注点, 可以通过AOP方法模块化, 进而借助Spring AOP框架实现声明式事务管理


如何为某个方法添加声明式事务:
  1. 配置出事务管理器
  1. <bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="tm">
  2. <constructor-arg name="dataSource" ref="dataSource"/>
  3. </bean>

记得导入AOP模块的jar包

  1. 开启基于注解的事务控制, 依赖tx名称空间
<tx:annotation-driven transaction-manager="tm"/>
  1. 给事务方法添加@Transactional注解

isolation: Isolation 事务隔离等级可能造成的并发问题:
  • 读未提交: 导致脏读;
    例如:
    事务1                    事务2
    开启事务                  开启事务
    读字段1数据 ->结果为100 ①            
                              修改字段1数据为200 ②
    读字段1数据 ->结果为200 ③
                              回滚 ④
    读字段1数据 ->结果为100 ⑤
    


在第3步时读取数据后, 数据被回滚不存在了

  • 读已提交: 避免了脏读, 无法避免不可重复读;
    例如:
    事务1                    事务2
    开启事务                  开启事务
    读字段1数据 ->结果为100 ①            
                              修改字段1数据为200 ②
    读字段1数据 ->结果为200 ③
                              提交 ④
    读字段1数据 ->结果为200 ⑤
    

从步骤1, 3可发现事务1读到了不同数据

  • 可重复毒(快照读): 避免了脏读, 不可重复读
    例如:``` 事务1 事务2 开启事务 开启事务 读字段1数据 ->结果为100 ①
                          修改字段1数据为200 ②
    
    读字段1数据 ->结果为100 ③
                          提交 ④
    
    读字段1数据 ->结果为100 ⑤ ```

可发现事务1在读取的数据都没有变化

mysql数据库的可重复读隔离级别也避免了幻读问题

有事务的业务逻辑, 容器中保存的是这个业务逻辑的代理对象


并发修改同一个数据下的排队
事务1                        事务2
修改字段1数据为100
                        修改字段2数据为200
                        等待前面的事务提交或回滚
提交
                        完成修改
                        提交

事务的传播行为

5.声明式事务 - 图1

传播行为可以设置事务方法是不是和之前的大事务共享一个事务(使用同一条连接)

propagation = Propagation.REQUIRED的事务方法的其他属性均会继承自上级事务, 自身属性失效; REQUIRED_NEW的事务方法其属性均生效

REQUIRED: 将之前事务的用的连接(connection)传递给该方法使用
REQUIRED_NEW: 直接新建一条连接给该方法使用

本类事务之间调用的就是同一个事务