暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

浅谈Spring事务传播行为

加耀 2018-12-26
363


在前面的文章中,我们有了解到mysql数据库索引原理及mysql数据库事务及其事务的实现原理数据库锁。

 

mysql的事务中,有四种事务隔离级别,分别解决了 脏读、不可重复读、幻读的问题。

 

在事务管理方面,除了事务隔离级别可以完善事务,还有哪些其它的方式可以来达到这种类似的效果呢?这个时候,我们可以看一下Spring为我们提供的解决方案。

 

我们在平时编写java代码时,只需要在响应的服务层上添加一个@Transactional注解即可,@Transactional注解中有配置响应的事务传播行为(Transaction Propagation Behavior)

 

那么,@Transactional注解,都为我们提供了哪些传播行为呢?我们一起来探索一下。

 

我们可以看一下@Transactional注解里面是怎么写的。

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {

   @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 {};
}


其中,事务的传播行为为:Propagation,默认值为:Propagation.REQUIRED

Spring中一共提供了7种事务传播行为,分别如下:

/**
* Spring
提供的7种事务传播行为
*/
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;
   
}
}


要理解事务的传播行为,我们首先需要理解一下事务是如何传播的,从哪来,到哪去。我们在学习事务的时候,都知道事务的原子性,也就是被添加的事务的方法为一个最小原子不可再分隔。

 

那么,事务的传播肯定是从方法A传递到方法B了。而Spring解决的只是方法之间的事务传播。

 

比如:

1、方法A有事务,方法B也有事务

2、方法A有事务,方法B没有事务

3、方法A没有事务,方法B有事务

4、方法A没有事务,方法B也没有事务

 

Spring7种事务传播,刚好四种对应了上面提到的四种,另外还有三种特殊的事务传播。

 

假设事务从方法A传播到方法B,用户需要面对方法B,此时,我们编写的方法A上有事务没有呢?

 

(1)  、如果此时方法A没有事务,那么就新建一个事务;如果有,就加入当前事务。这就是Propagation.REQUIRED,它是Spring默认的事务传播行为,适合绝大多数情况。

 

(2)  、如果没有,就新建一个任务;如果有,就将当前事务挂起。这就是Propagation.REQUIRES_NEW,意思就是新建一个事务,它和原来的事务没有任何关系了。

 

(3)  、如果没有,就新建一个任务;如果有,就在当前事务中嵌套其他事务。这就是Propagation.NESTED,也就是嵌套事务,所嵌套的子事务与主事务之间是有关联的(当主事务提交或回滚,子事务也会提交或回滚)

 

(4) 、如果没有,就以非事务方式执行;如果有,就在当前事务中嵌套其他事务。这就是Propagation.SUPPORTS,这种方式非常随意,没有就是没有,有就有,有点无所谓的态度。

 

(5) 、如果没有,就以非事务方式执行;如果有,就将当前事务挂起。这就是Propagation.NOT_SUPPORTED,这种方式非常强硬,没有就是没有,有也不支持,挂起来,不管它。

 

(6)  、如果没有,就以非事务方式执行;如果有,就抛出异常。这就是Propagation.NEVER,这种方式非常强硬,没有就是没有,有了反而报错。

 

(7)  、如果没有,就抛出异常;如果有,就使用事务。这就是Propagation.MANDATORY,这种方式是最强硬的,没有事务就直接报错。

 

怎么样,感觉是不是有种豁然开朗的感觉。

 

绝大多数情况下,我们使用Spring默认的事务传播行为即可满足所有的需求。

 

但是不用并不代表我们不去了解,毕竟这个是非常强大的。

 

 

2018122520:13:48

 


文章转载自加耀,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论