
这里主要介绍注解中三个常见属性:
rollbackFor:异常回滚属性。指定能够触发事务回滚的异常类型。可以指定多个异常类型Isolation:事务的隔离级别。默认值为 Isolation.DEFAULTPropagation:事务的传播机制。默认值为 Propagation.REQUIREDrollbackFor@Transactional 默认只在遇到 RuntimeException 和 Error 时才会回滚,而非运行时异常不回滚。

如果我们需要所有异常都回滚,需要来配置 @Transactional 注解当中的 rollbackFor 属性,通过这个属性指定出现何种异常类型时事务进行回滚。
// Controller 层
@RequestMapping("/r2")
public String r2(String name, String password) throws IOException {
userService.registryUserWithTx(name, password);
return "r2";
}
// Service 层
@Transactional(rollbackFor = Exception.class)
public void registryUserWithTx(String name, String password) throws IOException {
userRepository.save(new User(name, password));
log.info("用户数据插入成功");
if (true) {
throw new IOException(); // 模拟异常
}
}发现虽然程序抛出了异常,但是事务依然进行了回滚!
Isolation隔离级别 | 含义 |
|---|---|
Isolation.DEFAULT | 以连接的数据库的事务隔离级别为主 |
Isolation.READ_UNCOMMITTED | 读未提交 |
Isolation.READ_COMMITTED | 读已提交 |
Isolation.REPEATABLE_READ | 可重复读 |
Isolation.SERIALIZABLE | 串行化 |
它的实现如下所示:
public enum Isolation {
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 中事务隔离级别可以通过 @Transactional 中的 isolation 属性进行设置:
@Transactional(isolation = Isolation.READ_COMMITTED)
@RequestMapping("/r3")
public String r3(String name,String password) throws IOException {
//... 代码省略
return "r3";
}Propagation事务传播机制就是: 多个事务方法存在调用关系时,事务是如何在这些方法间进行传播的。
比如有两个方法 A,B 都被 @Transactional 修饰,A 方法调用 B 方法
A 方法运行时,会开启一个事务。当 A 调用 B 时,B 方法本身也有事务,此时 B 方法运行时,是加入 A 的事务呢,还是创建一个新的事务呢?
这就涉及到了事务的传播机制。


@Transactional 注解支持事务传播机制的设置,通过 propagation 属性来指定传播行为。
传播机制 | 作用 |
|---|---|
Propagation.REQUIRED | 默认的事务传播级别。如果当前存在事务,则加入该事务。如果当前没有事务,则创建一个新的事务。 |
Propagation.SUPPORTS | 如果当前存在事务,则加入该事务。如果当前没有事务,则以非事务的方式继续运行。 |
Propagation.MANDATORY | 如果当前存在事务,则加入该事务。如果当前没有事务,则抛出异常。 |
Propagation.REQUIRES_NEW | 如果当前存在事务,则把当前事务挂起。也就是说不管外部方法是否开启事务,Propagation.REQUIRES_NEW 修饰的内部方法都会新开启自己的事务,且开启的事务相互独立,互不干扰。 |
Propagation.NOT_SUPPORTED | 以非事务方式运行,如果当前存在事务,则把当前事务挂起,不使用它。 |
Propagation.NEVER | 以非事务方式运行,如果当前存在事务,则抛出异常。 |
Propagation.NESTED | 如果当前存在事务,则创建一个事务作为当前事务的子事务来运行。如果当前没有事务,则创建一个新的事务。 |
实现类如下所示:
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;
}
}nested 和 required 的区别REQUIRED 加入事务会导致整个事务全部回滚。NESTED 嵌套事务可以实现局部回滚,不会影响上一个方法中执行的结果。嵌套事务之所以能够实现部分事务的回滚,是因为事务中有一个保存点(savepoint)的概念,嵌套事务进入之后相当于新建了一个保存点,而滚回时只回滚到当前保存点。
REQUIRED是加入到当前事务中,并没有创建事务的保存点,因此出现了回滚就是整个事务回滚,这就是嵌套事务和加入事务的区别!
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。