zoukankan      html  css  js  c++  java
  • Spring 与 Mybatis 的事务管理

    问题:Spring 与 Myabatis 整合后,为什么 DAO 不提交事务,但是数据能够插入数据库中?

    1. Mybatis 提供的连接池对象 —> 创建 Connection
      Connection.setAutoCommit(false) 手工的控制了事务,操作完成后,需要手工提交。
    2. Druid(C3P0、DBCP)作为连接池 —> 创建 Connection
      Connection.setAutoCommit(true) 默认值为 true,保持自动控制事务,一条 sql 自动提交。

    答案:因为 Spring 与 Mybatis 整合时,引入了外部连接池对象,保持自动的事务提交这个机制Connection.setAutoCommit(true),不需要手工进行事务的操作,也能进行事务的提交。

    注意:实战中,还是会手工控制事务(多条SQL一起成功,一起失败),后续 Spring 通过 事务控制 解决这个问题

    1. 事务回顾

    事务的 4 大特点: ACID

    • Atomicity 原子性
    • Consistency 一致性
    • Isolation 隔离性
    • Durability 持久性

    如何控制事务?(JDBC、Mybatis)

    JDBC
    Connection.setAutoCommit(false);
    Connection.commit();
    Connection.rollback();
    
    Mybatis

    Mybatis 自动开启事务
    sqlSession.commit();,底层还是调用的 Connection
    sqlSession.rollback();,底层还是调用的 Connection

    2. Spring 中控制事务的开发

    3. Spring 中的事务属性(Transaction Attribute)

    什么是事务属性?

    描述物体特征的一系列值(性别、身高、体重)

    事务属性:描述事务特征的一系列值

    如何添加事务属性?
    @Transactional(isolation=, propagation=, readOnly=,timeout=,rollbackFor,noRollbackFor=,)
    

    隔离属性(ISOLATION)

    描述了事务解决并发问题的特征。
    1. 什么是并发?
      多个事务(用户)在同一时间,访问操作了相同的数据。
      同一时间:0.000 几秒左右
    2. 并发会产生那些问题?
      • 脏读
      • 不可重复读
      • 幻影读
    3. 并发问题如何解决?
      通过隔离属性解决,隔离属性中设置不同过的值,解决并发处理的过程中的问题。
    事务并发产生的问题:
    1. 脏读
      一个事务,读取了另一个事务中没有提交的数据,会在本事务中产生数据不一样的现象
      解决方案:@Transaction(isolation = Isolation.READ_COMMITTED)
    2. 不可重复读
      一个事务中,多次读取相同的数据,但是读取结果不一样,会在本事务中产生数据不一样的现象
      注意:1.不是脏读 2.在一个事务中
      解决方案:@Transaction(isolation = Isolation.REPEATABLE_READ)
      本质:一把行锁(对数据库表的某一行加锁)
    3. 幻影读
      一个事务中,多次对整表进行查询统计,但是结果不一样,会在本事务中产生数据不一致的问题
      解决方案:@Transaction(isolation = Isolation.SERIALIZABLE)
      本质:表锁(对数据库某个表加锁)
    安全与效率对比:
    • 并发安全:SERIALIZABLE > READ_ONLY > READ_COMMITTED
    • 运行效率:READ_COMMITTED > READ_ONLY > SERIALIZABLE
    默认的隔离属性:

    Spring 默认会指定为 ISOLATION_DEFAULT,调用不同数据库所设置的默认隔离属性

    • MySQL:REPEATABLE_READ
    • Oracle:READ_COMMITTED

    查看数据库的默认隔离属性:

    • MySQL:SELECT @@tx_isolation;
    • Oracle:较麻烦,建议百度。

    隔离属性在实验中的建议

    • 推荐使用 Spring 默认指定的 ISOLATION_DEFAULT
    • 未来的实战中,遇到并发访问的情况,很少见
    • 如果真的遇到并发问题,解决方案:乐观锁
      Hibernate(JPA):version
      MyBatis:通过拦截器自定义开发

    传播属性(PROPAGATION)

    概念:描述了事务解决 嵌套问题 的特征。

    事务的嵌套

    指的是一个大的事务中,包含了若干个小的事务。

    事务嵌套产生的问题

    大事务中融入了很多小的事务,他们彼此影响,最终就导致外部大的事务丧失了事务的原子性。

    传播属性的值及其用法:
    传播属性的值 外部不存在事务 外部存在事务 用法 备注
    REQUIRED(默认) 开启新的事务 融合到外部事务中 @Transactional(propagation = Propagation.REQUIRED) 增、删、改方法
    SUPPORTS 不开启事务 融合到外部事务中 @Transactional(propagation = Propagation.SUPPORTS) 查询方法
    REQUIRES_NEW 开启新的事务 挂起外部事务,创建新的事务 @Transactional(propagation = Propagation.REQUIRES_NEW) 日志记录方法中
    NOT_SUPPORTED 不开启事务 挂起外部事务 @Transactional(propagation = Propagation.NOT_SUPPORTED) 极其不常用
    NEVER 不开启事务 抛出异常 @Transactional(propagation = Propagation.NEVER) 极其不常用
    MANDATORY 抛出异常 融合到外部事物中 @Transactional(propagation = Propagation.MANDATORY) 极其不常用
    Spring 中传播属性的默认值是:REQUIRED

    推荐传播属性的使用方式:

    • 增删改 方法:使用默认值 REQUIRED
    • 查询 方法:显示指定传播属性的值为 SUPPORTS

    只读属性(readOnly)

    针对于 只进行查询操作的业务方法,可以加入只读属性,提高运行效率。
    默认值:false

    @Transactional(readOnly = true)
    

    超时属性(timeout)

    指定了事务等待的最长时间。

    为什么事务会进行等待?
    1. 当前事务访问数据时,有可能访问的数据被别的事务进行加锁的处理,那么此时本事务就必须进行等待。
    2. 等待时间:单位是 秒
    3. 如何使用:@Transactional(timeout = 2)
    4. 超时属性的默认值:-1
      -1 表示超时属性由对应的数据库来指定(一般不会主动指定,-1 即可)

    异常属性

    Spring 事务处理过程中:
    • 默认对于 RuntimeException 及其子类,采用 回滚 的策略。
    • 默认对于 Exception 及其子类,采用 提交 的策略。
    使用方法:
    @Transactional(rollbackFor = java.lang.Exception.class, xxx, xxx)
    @Transactional(noRollbackFor = java.lang.RuntimeException, xxx, xxx)
    

    事务属性常见配置总结

    1. 隔离属性:默认值
    2. 传播属性:Required(默认值)增删改、Supports 查询操作
    3. 只读属性:readOnly=false 增删改,true 查询操作
    4. 超时属性:默认值 -1
    5. 异常属性:默认值
    开发建议

    增删改操作:@Transactional
    查询操作:@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)

    没有修不好的电脑
  • 相关阅读:
    Java内存模型之重排序
    JAVA虚拟机:对象的创建过程
    单链表——基本操作
    new File()
    JVM回收方法区内存
    强软弱虚---强引用、软引用、弱引用、虚引用
    线性表(二)——链式存储
    JVM中判断对象是否存活的方法
    GC算法 垃圾收集器
    线性表(一)——顺序结构
  • 原文地址:https://www.cnblogs.com/duniqb/p/13274699.html
Copyright © 2011-2022 走看看