上期我们讲解了Spring事务的两种实现,其中声明式注解使用了 @Transactional 注解, 接下来我们学习 该注解的使用细节。
我们主要学习 @Transactional注解当中的三个常见属性:
rollbackFor:异常回滚属性,指定能够出发事务回滚的异常类型,可以指定多个异常类型
Isolation:事务的隔离级别,默认值为:Isolation.DEFAULT
@Transactional 默认只在遇到运行时异常和Error时才会回滚,非运行时异常不回滚,即 error及子类,RuntimeException 及子类 才会回滚:
解上次代码我们添加一个测试方法:
- @Transactional
- @RequestMapping("/test1")
- public Boolean test1(String userName, String password) throws IOException {
- userService.registry(userName, password);
- if(true) {
- throw new IOException();
- }
- return true;
- }
不会回滚
- @Transactional
- @RequestMapping("/test1")
- public Boolean test1(String userName, String password) throws RuntimeException {
- userService.registry(userName, password);
- if(true) {
- throw new RuntimeException();
- }
- return true;
- }
会回滚
我们可以通过配置 @Transactional 注解中的 rollbackFor 属性来指定出现何种异常类型时事务进行回滚。
- @Transactional(rollbackFor = Exception.class)
- @RequestMapping("/test1")
- public Boolean test1(String userName, String password) throws IOException {
- userService.registry(userName, password);
- if(true) {
- throw new IOException();
- }
- return true;
- }
会回滚
Spring 中事务隔离级别有5种:
- 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 中事故隔离级别可以通过 @Transational 中的 isolation 属性进行设置
- @Transactional(isolation = Isolation.READ_UNCOMMITTED)
- @RequestMapping("/test")
- public Boolean test(String userName, String password) throws IOException {
- userService.registry(userName, password);
- if(true) {
- throw new IOException();
- }
- return true;
- }
事务的传播机制是:多个事务方法存在调用关系时,事务是如何在这些方法间进行传播的。
例:
现有两个方法 A 和 B 都被 @Transactional 修饰, A方法中调用了B方法,A方法运行时会开启一个事务,当 A 调用 B 时,B 方法本身也有事务,此时B方法是加入 A 的事务还是创建一个新的事务,就涉及到了事务的传播机制。
@Transactional 注解支持事务传播机制的设置,通过 propagation 属性来指定传播行为。
Spring 事务传播机制有以下7种:
这里我们解释以下 Propagation.NESTED , 在嵌套事务的情况下,无论哪个方法发生异常都会导致所有的事务回滚,不过与Propagation.REQUIRED的区别在于,如果 子事务发生异常,可以使用try catch 语句,在catch中把子事务单独进行回滚,而不影响其他事务(因为异常被捕获了,其他事务感知不到),但是如果父事务进行了回滚,则子事务也一定都会回滚。