Fork me on GitHub

Spring篇——简单理解@Transactional注解中propagation的使用

前言

有一段时间没有更新记录了,正好今天是周五。公司给的一个小项目里面有自己封装的框架,闲暇时光看一看…

无意之中看到了封装分页的的底层方法中使用了这样的注解。

1
2
3
4
@Transactional(
readOnly = true,
propagation = Propagation.NOT_SUPPORTED
)

那我就顺便学习,总结下@Transactional注解当中propagation属性的一些用法和特征吧,充充电。

看看源码

@Transactional有哪些属性呢

Spring的事务管理当中,我们一直都是使用@Transactional注解来对事务进行设定的。简而言之,在类或者方法上使用@Transactional注解,并且传输属性获得相应的Transaction特性。Spring当中对于@Transactional注解的属性从源码查看如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {
String value() 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 {};
}

从源码当中可以看出@Transactionalpropagation isolation timeout readOnly rollbackForClassName noRollbackForClassName 等属性。

isolation是设置事务隔离,timeout事务超时,readOnly 定义该事务的方法只读,默认为false,rollbackForClassName 定义回滚条件,比如发生RuntimeException时候发生回滚,noRollbackForClassName 不回滚,有些异常时正常情况,不进行回滚。通过这些属性可以定义出满足复杂应用事务的要求。

具体看看propagation属性

在Service层类上使用@Transactional注解,声明这个类所有方法需要事务管理,每一个业务方法开始时候都会打开一个事务,每一个方法所需要的事物管理级别特性的不同,就需要我们使用 @Transactional 当中这些属性来操作了。

Spring默认情况下是对RuntimeException运行期异常进行事务回滚,并且只对于运行时异常当中的unchecked异常回滚,对于checked异常就不回滚,对于checked unchecked异常分类不在这里记录,之后再进行记录。

上面说到默认对运行时异常当中的unchecked异常进行回滚,那么问题来了,我们想要实现对checked异常进行回滚怎么办呢?当然有方法可以处理的,就需要使用到上面说到的属性。

  • checked异常回滚
1
@Transactional(rollbackFor = Exception.class)
  • unchecked异常不回滚
1
@Transactional(noRollbackFor = RuntimeException.class)
  • 查询操作不需要事务
1
@Transactional(propagation = Propagation.NOT_SUPPORTED)

或者

1
@Transactional(propagation = Propagation.NOT_SUPPORTED,readOnly = true)

将这个方法做成了一个只读事务,提高效率。

说了这么多还不知道Propagation是个什么东西呢,这是一个枚举类型,里面定义了该属性的各种意义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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;
}
}

Propagation的各枚举含义

上面已经将Propagation当中各个枚举列举出来了,它们都是什么含义呢?

  • REQUIRED(必须)

业务方法需要在一个容器当中运行。如果该方法运行时候已经处在一个事务中,那么加入该事务,否则自己新建事务。
这个是默认值

  • SUPPORTS(支持)

如果业务方法在某个事务范围内被调用,则成为该事务的一部分。如果该业务方法在事务范围之外被调用,则在没有事务环境下运行。(有则改之无则加勉,有则用之无则不用)

  • MANDATORY(强制性)

业务方法只能在一个已经存在的事物当中执行,不能够自己发起事务。如果该业务方法在没有事务环境下运行则会抛出异常(IllegalTransactionStateException)。

  • REQUIRES_NEW(需要新的)

不管事务是否存在,该业务方法都会自己新建一个新的事务。如果业务方法已经运行在一个事务当中,则原来的事务被挂起,新事务被创建。

  • NOT_SUPPORTED

业务方法不需要事务。如果该业务方法运行没有关联到事务,则不会为其开启事务;如果该业务方法在一个事务当中被调用,该事务被挂起,调用结束后,原先事务恢复执行。

  • NEVER

业务方法绝对不能再事务范围内执行。如果在就抛出异常(IllegalTransactionStateException)。只有不关联任务事务才正常执行。

  • NESTED

业务方法执行时存在一个活动的事务,那么该方法运行在一个嵌套的事务当中,作为子事务。如果没有活动事务则按照REQUIRED 属性来执行。该属性使用一个单独的事务,拥有很多个可以回滚的保存点,内部事务的回滚不会对外部事务造成影响。

举个栗子吧

上面说了这么多了,下面举个栗子,说一下吧。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Service
@Transactional
public class TestTransactional {

@Autowired
private IExampleDao exampleDao;

@Transactional
public void internalMethod(){
exampleDao.doSomething();
externalMethod();
}

@Transactional
public void externalMethod(){
exampleDao.doSomething();
}
}

先上一段伪代码。在Service层定义两个方法,分别为internalMethodexternalMetod。然后里面都调用exampleDao当中的doSomething()方法。下面就来根据上面列举出来的Propagation的属性来讨论事务。

Propagation属性 externalMethod internalMethod
Propagation.REQUIRED(默认) 此时无事务,新开始一个事务并在其中运行 externalMethod方法的事务中运行
Propagation.SUPPORTS externalMethod无事务,不在事务中运行 加入externalMethod事务中运行
Propagation.MANDATORY 抛出异常 externalMethod事务中运行
Propagation.REQUIRES_NEW 新开启事务并在其中运行 挂起externalMethod中事务,直至internalMethod中新开事务运行完毕
Propagation.NOT_SUPPORTED externalMethod无事务,不在事务中运行 挂起externalMethod中事务,直至internalMethod方法执行完毕(注意这里不是事务,是方法)
Propagation.NEVER externalMethod无事务,不在事务中运行 抛出异常(不能在事务中运行)

下回就统计统计上面说到的unchecked checked 异常吧。

联系

聪聪的独立博客 ,一个喜欢技术,喜欢钻研的95后。如果你看到这篇文章,千里之外,我在等你联系。

坚持原创技术分享,您的支持将鼓励我继续创作!