谈谈你对Spring事务的理解【面试】

前言

面试中,Spring的事务问得比较多,特别是Spring事务的传播行为和隔离级别,下面就让我们一起来复习下,首先我们要清楚事务的四大特征(ACID):

  • 原子性(atomicity)
  • 一致性(consistency)
  • 隔离性(isolation)
  • 持久性(durability)

1、概念

Spring有两种事务处理方式,一种是声明式事务,另外一种是编程式事务。

  • 声明式事务:底层建立在IoC和AOP的基础上,在方法的前后进行拦截,在方法执行前创建或者加入一个事务,方法执行后提交或者回滚事务。
  • 编程式事务:在方法的前后手动的开启和关闭事务,控制的粒度比声明式事务要小,可以达到代码块级别,但代码会很臃肿和复杂,项目中一般不会用。

2、声明式事务

在配置声明式事务管理的时候,我们用到最多的是注解方式,我们看下@Transactional这个注解的源码:

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {
	//定义事务管理器,这里的value是IoC容器中的Bean id
    @AliasFor("transactionManager")
    String value() default "";
    @AliasFor("value")
    String transactionManager() default "";
    //传播行为
    Propagation propagation() default Propagation.REQUIRED;
    //隔离级别
    Isolation isolation() default Isolation.DEFAULT;
    //超时时间
    int timeout() default -1;
    //是否开启只读事务
    boolean readOnly() default false;
    //回滚事务的异常类定义
    Class<? extends Throwable>[] rollbackFor() default {};
    //回滚事务的异常类名称定义
    String[] rollbackForClassName() default {};
    //当产生哪些异常不回滚
    Class<? extends Throwable>[] noRollbackFor() default {};
    //当产生哪些异常不回滚类名称定义
    String[] noRollbackForClassName() default {};
}

上面的属性中,这里重点解释传播行为和隔离级别

3、传播行为

下面是定义传播行为Propagation枚举类的源码:

public enum Propagation {
	//支持当前事务(如果当前存在事务,则加入到当前事务,总共一个事务),如果不存在 就新建一个(默认)
    REQUIRED(0),
    //支持当前事务,如果不存在,就不使用事务
    SUPPORTS(1),
    //支持当前事务,如果不存在,抛出异常
    MANDATORY(2),
    //如果有事务存在,挂起当前事务,新建一个新的事务(新建的事务是独立,与当前事务无关)
    REQUIRES_NEW(3),
    //以非事务方式运行,如果有事务存在,挂起当前事务
    NOT_SUPPORTED(4),
    //以非事务方式运行,如果有事务存在,抛出异常
    NEVER(5),
    //如果当前事务存在,则嵌套事务执行,作为当前事务中的一个子事务(依赖外层的事务,外层事务失败,子事务也要回滚)
    NESTED(6);
    private final int value;
    private Propagation(int value) {
        this.value = value;
    }
    public int value() {
        return this.value;
    }
}

4、隔离级别

先看下几个基本的概念:

  1. 脏读:一个事务读取到另一事务未提交的更新数据。
  2. 不可重复读:在同一事务中, 第一次读取和第二次读取过程中,有另外一个事务更新提交了数据,导致多次读取同一数据返回的结果不同。
  3. 幻读 : 第一个事务正在查询符合某一条件的数据,这时,另一个事务又插入了一条符合条件的数据,第一个事务在第二次查询符合同一条件的数据时,发现多了一条前一次查询时没有的数据,仿佛幻觉一样,这就是幻像读。

【提示】:不可重复读针对的是更新和删除操作导致数据不一致,幻读针对的是插入操作导致的数据不一致。

下面是定义隔离级别Isolation枚举类的源码:

public enum Isolation {
	//Spring默认的隔离级别,使用数据库默认的事务隔离级别
	//MYSQL: 默认为REPEATABLE_READ级别
	//SQLSERVER: 默认为READ_COMMITTED
    DEFAULT(-1),
    //读取未提交数据(会出现脏读, 不可重复读) 基本不使用
    READ_UNCOMMITTED(1),
    //读取已提交数据(会出现不可重复读和幻读)
    READ_COMMITTED(2),
    //可重复读(会出现幻读)
    REPEATABLE_READ(4),
    //串行化(防止脏读,不可重复读外,还避免了幻像读,但花费代价很大)
    SERIALIZABLE(8);
    private final int value;
    private Isolation(int value) {
        this.value = value;
    }
    public int value() {
        return this.value;
    }
}

结束语

本文较为详细的介绍了Spring事务的相关知识点,大家可以自己在本地亲自实践下,加深自己的理解。

原创文章 55 获赞 76 访问量 17万+

猜你喜欢

转载自blog.csdn.net/cool_summer_moon/article/details/106025724