Spring事务传播机制

Spring事务传播机制

  • 回顾
  • 简单介绍
  • 事务的传播机制有哪些
    • Propagation.REQUIRED
    • Propagation.SUPPORTS
    • Propagation.MANDATORY
    • Propagation.REQUIRES_NEW
    • Propagation.NOT_SUPPORTED
    • Propagation.NEVER
    • Propagation.NESTED
  • 实例
    • REQUIRED
    • REQUIRES_NEW
    • NEVER
    • NESTED
    • REQUIRED和NESTED的区别

回顾

Spring事务传播机制_第1张图片

之前我们学习了Spring如何进行事务的实现和运用,今天我们来学习Spring事务的传播机制

简单介绍

Spring事务的传播机制就是当存在多个事务的时候,且多个事务方法存在调用关系,事务是如何在这些方法中进行传播的

事务的传播机制有哪些

@Transactional注解支持事务传播机制的设置,通过propagation属性来指定传播行为,
以A方法调用B方法为例,A⽅法运⾏时, 会开启⼀个事务. 当A调⽤B时, B⽅法本⾝也有事务, 此时B⽅法运⾏时, 是加⼊A的事务, 还是创建⼀个新的事务呢(使用自己的事务)?这个就涉及到了事务的传播机制.
Spring事务传播有以下七种机制:

Propagation.REQUIRED

默认的事务传播级别. 如果A存在事务, 则B加⼊该事务. 如果A没有事务, 则创建⼀个新的事务(事务中包含AB).

Propagation.SUPPORTS

如果A存在事务, 则B加⼊该事务. 如果A没有事务, 则A,B以都以⾮事务的⽅式继续运⾏.

Propagation.MANDATORY

强制性. 如果A存在事务, 则B加⼊该事务. 如果A没有事务, 则抛出异常.

Propagation.REQUIRES_NEW

创建⼀个新的事务(B) 如果A存在事务, 则把A事务挂起. 也就是说不管A⽅法是否开启事务, Propagation.REQUIRES_NEW修饰的B⽅法都会新开启一个事务, 且开启的事务相互独⽴, 互不⼲扰,就算A用A的事务,B用B的事务,A没有就算了

Propagation.NOT_SUPPORTED

B以⾮事务⽅式运⾏, 如果A存在事务, 则把A事务挂起(不⽤).

Propagation.NEVER

以⾮事务⽅式运⾏, 如果A存在事务, 则抛出异常.

Propagation.NESTED

如果A存在事务, 则创建⼀个事务作为A事务的嵌套事务来运⾏. 如果A没有事务, 则该取值等价于PROPAGATION_REQUIRED

实例

上面其中机制,我们只需要重点掌握两个:
REQUIRED
REQUIRES_NEW

REQUIRED

@RestController
public class PropagationController {
    @Autowired
    private UserInfoService userInfoService;
    @Autowired
    private LogInfoService logInfoService;
    @Transactional( propagation = Propagation.REQUIRED)
    @RequestMapping("/insertInfo")
    public void insertInfo(String userName,String password){
        userInfoService.insert(userName,password);
        logInfoService.insert(userName,"用户注册成功");
    }
}

@Service
public class LogInfoService {
    @Autowired
    private LogInfoMapper logInfoMapper;
    @Transactional( propagation = Propagation.REQUIRED)
    public Integer insert(String userName, String op) {
    	Integer i = 10/0;
        return logInfoMapper.insert(userName,op);
    }
}
@Service
public class UserInfoService {
    @Autowired
    private UserInfoMapper userInfoMapper;
    @Transactional( propagation = Propagation.REQUIRED)
    public Integer insert(String userName, String password) {
        return userInfoMapper.insert(userName,password);
    }
}

运⾏程序,程序报错,发现数据库没有插⼊任何数据
流程描述:

  1. insertInfo⽅法开始事务
  2. ⽤⼾注册, 插⼊⼀条数据 (执⾏成功) (和insertInfo使⽤同⼀个事务)
  3. 记录操作⽇志, 插⼊⼀条数据(出现异常, 执⾏失败) (和insertInfo使⽤同⼀个事务)
  4. 因为步骤3出现异常, 事务回滚. 步骤2和3使⽤同⼀个事务 所以步骤2的数据也回滚了

REQUIRES_NEW

将上述代码中将上述UserService和LogService的传播机制改为 REQUIRES_NEW
运行程序,我们观察程序,可以看到,user_info中已经成功新增了一条数据,但是log_info中却并没有成功
这是因为REQUIRES_NEW的调用方与被调用着的事务是独立的,之间互不影响.

NEVER

将UserService中的事务传播机制改为NEVER
运行程序,程序报错,数据也没有插入成功,这是因为NEVER的调用方不能有事务,否则会报错,并回滚

NESTED

将UserService和LogService中的传播机制改为NESTED
运行程序,发现似乎和REQUIRED一样,但是当我们手动给LogService进行回滚,就会发现,日志表新增失败了,但是用户表注册成功了,也就是说,调用方的事务包含被调用者的事务,但是被调用者的事务也是一个独立的事务,因此可以实现局部回滚

REQUIRED和NESTED的区别

整个事务如果全部执⾏成功, ⼆者的结果是⼀样的
如果事务⼀部分执⾏成功, REQUIRED加⼊事务会导致整个事务全部回滚. NESTED嵌套事务可以实现局部回滚, 不会影响上⼀个⽅法中执⾏的结果

你可能感兴趣的:(spring,数据库,java)