什么是事务

  1. 事务是数据库的概念,事务代表了一组数据库操作,数据库操作要么全部成功,要么全部失败。
  2. 事务有几个特征
    1. 原子性
    2. 一致性
    3. 隔离性
    4. 持久性

具体事务可以看我之前的数据库文章
03 | 事务

Spring 事务操作

事务的配置

<!--    开启组件扫描-->
        <context:component-scan base-package="springDemo"></context:component-scan>
<!--    注入datasource-->
        <bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource">
            <property name="url" value="jdbc:mysql://localhost:3306/hello"></property>
            <property name="username" value="root"></property>
            <property name="password" value="root"></property>
            <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
        </bean>
<!--    配置jdbcTemplate-->
        <bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate">
            <property name="dataSource" ref="dataSource"></property>
        </bean>
<!--        配置事务管理器-->
        <bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="dataSourceTransactionManager">
            <property name="dataSource" ref="dataSource"></property>
        </bean>
<!--    开启事务注解-->
        <tx:annotation-driven transaction-manager="dataSourceTransactionManager"></tx:annotation-driven>

在 Service 类上加上@Transactional 注解

  1. 无异常则直接提交
  2. 有异常则全部回滚

事务的传播行为

简单的理解就是多个事务方法相互调用时,事务如何在这些方法间传播。

举个栗子,方法 A 是一个事务的方法,方法 A 执行过程中调用了方法 B,那么方法 B 有无事务以及方法 B 对事务的要求不同都会对方法 A 的事务具体执行造成影响,同时方法 A 的事务对方法 B 的事务执行也有影响,这种影响具体是什么就由两个方法所定义的事务传播类型所决定。

** 在这里要做一个重要提示:Spring 中事务的默认实现使用的是 AOP,也就是代理的方式,如果大家在使用代码测试时,同一个 Service 类中的方法相互调用需要使用注入的对象来调用,不要直接使用 this.方法名来调用,this.方法名调用是对象内部方法调用,不会通过 Spring 代理,也就是事务不会起作用**

REQUIRED(Spring 默认的事务传播类型)

如果当前没有事务,则自己新建一个事务,如果当前存在事务,则加入这个事务

SUPPORTS

当前存在事务,则加入当前事务,如果当前没有事务,就以非事务方法执行

MANDATORY

当前存在事务,则加入当前事务,如果当前事务不存在,则抛出异常。

REQUIRES_NEW

创建一个新事务,如果存在当前事务,则挂起该事务。

NOT_SUPPORTED

始终以非事务方式执行,如果当前存在事务,则挂起当前事务
可以理解为设置事务传播类型为 NOT_SUPPORTED 的方法,在执行时,不论当前是否存在事务,都会以非事务的方式运行

NEVER

不使用事务,如果当前事务存在,则抛出异常
很容易理解,就是我这个方法不使用事务,并且调用我的方法也不允许有事务,如果调用我的方法有事务则我直接抛出异常

NESTED

如果当前事务存在,则在嵌套事务中执行,否则 REQUIRED 的操作一样(开启一个事务)
这里需要注意两点:

  1. 和 REQUIRES_NEW 的区别
    REQUIRES_NEW 是新建一个事务并且新开启的这个事务与原有事务无关,而 NESTED 则是当前存在事务时(我们把当前事务称之为父事务)会开启一个嵌套事务(称之为一个子事务)。
    在 NESTED 情况下父事务回滚时,子事务也会回滚,而在 REQUIRES_NEW 情况下,原有事务回滚,不会影响新开启的事务。
  2. 和 REQUIRED 的区别
    REQUIRED 情况下,调用方存在事务时,则被调用方和调用方使用同一事务,那么被调用方出现异常时,由于共用一个事务,所以无论调用方是否 catch 其异常,事务都会回滚
    而在 NESTED 情况下,被调用方发生异常时,调用方可以 catch 其异常,这样只有子事务回滚,父事务不受影响

事务的隔离级别

MySQL 的事务隔离级别有四个

  1. 读未提交
  2. 读已提交
  3. 可重复读
  4. 串行化

具体看 Mysql 笔记

spring 事务-xml 方式

配置事务管理器

配置通知

配置切入点和切面

spring 事务-注解方式

test