1.什么是事务传播行为

==事务传播行为是为了解决业务层方法相互调用的事务问题==

当一个事务方法被另外一个事务方法调用时,必须指定事务如何传播

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Service
Class A {
@Autowired
B b;
@Transactional(propagation = Propagation.xxx)
public void aMethod {
//do something
b.bMethod();
}
}

@Service
Class B {
@Transactional(propagation = Propagation.xxx)
public void bMethod {
//do something
}
}

图片

2.REQUIRED

Spring默认的事务传播行为

  • 如果外部方法没有开启事务的话,Propagation.REQUIRED修饰的内部方法会新开启自己的事务,且开启的事务相互独立,互不干扰。

  • 如果外部方法开启事务并且被Propagation.REQUIRED的话,所有Propagation.REQUIRED修饰的内部方法和外部方法均属于同一事务 ,只要一个方法回滚,整个事务均回滚。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//aMethod()和bMethod()使用的都是PROPAGATION_REQUIRED传播行为两者使用的就是同一个事务,只要其中一个方法回滚,整个事务均回滚。
@Service
Class A {
@Autowired
B b;
@Transactional(propagation = Propagation.REQUIRED)
public void aMethod {
//do something
b.bMethod();
}
}
@Service
Class B {
@Transactional(propagation = Propagation.REQUIRED)
public void bMethod {
//do something
}
}

aMethod()和bMethod()使用的都是PROPAGATION_REQUIRED传播行为两者使用的就是同一个事务,只要其中一个方法回滚,整个事务均回滚

3.REQUIRES_NEW

创建一个新的事务,如果当前存在事务,则把当前事务挂起。外部方法是否开启事务,Propagation.REQUIRES_NEW修饰的内部方法会新开启自己的事务,且开启的事务相互独立,互不干扰。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Service
Class A {
@Autowired
B b;
@Transactional(propagation = Propagation.REQUIRED)
public void aMethod {
//do something
b.bMethod();
}
}

@Service
Class B {
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void bMethod {
//do something
}
}

bMethod()使用PROPAGATION_REQUIRES_NEW事务传播行为修饰,aMethod还是用PROPAGATION_REQUIRED修饰的话。如果aMethod()发生异常回滚,bMethod()不会跟着回滚,因为 bMethod()开启了独立的事务。但是,如果 bMethod()抛出了未被捕获的异常并且这个异常满足事务回滚规则的话,aMethod()同样也会回滚,因为这个异常被 aMethod()的事务管理机制检测到了。

3.NESTED

如果当前存在事务,就在嵌套事务内执行;如果当前没有事务,就执行与TransactionDefinition.PROPAGATION_REQUIRED类似的操作。也就是说:

  • 在外部方法开启事务的情况下,在内部开启一个新的事务,作为嵌套事务存在。
  • 如果外部方法无事务,则单独开启一个事务,与 PROPAGATION_REQUIRED 类似。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Service
Class A {
@Autowired
B b;
@Transactional(propagation = Propagation.REQUIRED)
public void aMethod {
//do something
b.bMethod();
}
}

@Service
Class B {
@Transactional(propagation = Propagation.NESTED)
public void bMethod {
//do something
}
}

如果 bMethod() 回滚的话,aMethod()不会回滚。如果 aMethod() 回滚的话,bMethod()会回滚。

4.MANDATORY

如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。(mandatory:强制性)

5.SUPPORTS

如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。

6.NOT_SUPPORTED

以非事务方式运行,如果当前存在事务,则把当前事务挂起。

7.NEVER

以非事务方式运行,如果当前存在事务,则抛出异常。

8.事务失效

SpringAop自调用

当一个方法被标记了@Transactional 注解的时候,Spring 事务管理器只会在被其他类方法调用的时候生效,而不会在一个类中方法调用生效。

1
2
3
4
5
6
7
8
9
10
11
12
13
//事务失效
@Service
public class MyService {

private void method1() {
method2();
//......
}
@Transactional
public void method2() {
//......
}
}

@Transactional修饰的方法不是public方法

设置的 @TransactionalrollbackForpropagation 属性不正确,事务失效不回滚

@Transactional 注解的方法所在的类没有被 Spring 管理

底层使用的数据库不支持支持事务机制