Spring事务的七种传播方式

您所在的位置:网站首页 简述科研的类型七种分类方法 Spring事务的七种传播方式

Spring事务的七种传播方式

2024-06-28 05:16| 来源: 网络整理| 查看: 265

Spring事务

如果你作为一个开发者,不开事务就增删改,那我估计一天都活不下来就改走人了,事务很重要,简单来说事务就是连续一组的sql操作,一组动作都完成才能提交,但凡是一个环节出了异常那就得回滚到最初的状态 而传播方式则主要是指多个事务同时存在时,Spring如何处理事务,它们是否需要在同一个事务中运行;一个有事务的方法被另外有事务的方法调用时,这个事务应该如何运行;例如

methodA() { // 有事务 update; ServiceB.methodB(); // 又调用了另一个有事务的方法 异常; } methodB() { // 事务 update; } 7种传播方式

在这里插入图片描述

开事务

Spring容器中配置用注解的方式开事务,xml写我下面会说

1 REQUIRED

REQUIRED:表示如果当前存在一个事务,则加入该事务,否则将新建一个事务;这个是Spring事务默认传播行为

测试 @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT) public int incr(int balance, int id) { //传播方式request int result = studentMapper.updateBalance(balance, id); //新事务 studentService.decr(-100, 2); //制造异常引起incr这个事务回滚 int i = 1/0; return result ; } @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, rollbackFor = Throwable.class) public int decr(int balance, int id){ int result = studentMapper.updateBalance(balance, id); return result ; }

测试结果是两个方法对应的操作都不起作用,decr加入到了incr这个事务中,incr回滚导致decr也回滚

2 REQUIRES_NEW

表示不管是否存在事务,都创建一个新的事务,原来的事务挂起,新的事务执行完毕,继续执行老的事务;

测试

和刚才代码几乎一样,我只是把decr的传播方式改成了REQUIRES_NEW

@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT) public int incr(int balance, int id) { //传播方式request int result = studentMapper.updateBalance(balance, id); //新事务 studentService.decr(-100, 2); //制造异常 int i = 1/0; return result ; } /** 转出 */ @Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.DEFAULT, rollbackFor = Throwable.class) public int decr(int balance, int id) { int result = studentMapper.updateBalance(balance, id); return result ; }

而结果是decr这个事务不会被incr影响,最终导致"增加"这个事务回滚,"减少"这个事务会正常提交

3 SUPPORTS

表示如果当前存在事务,就加入该事务;如果当前没有事务,那就不使用事务;

测试 /** 转入 */ @Override public int incr(int balance, int id) {//没有事务 //传播方式request int result = studentMapper.updateBalance(balance, id); //新事务 studentService.decr(-100, 2); int i = 1/0; return result ; } /** 转出 */ @Transactional(propagation = Propagation.SUPPORTS, isolation = Isolation.DEFAULT, rollbackFor = Throwable.class) public int decr(int balance, int id) /*throws SQLException */{ int result = studentMapper.updateBalance(balance, id); //throw new SQLException("SQL异常"); return result ; }

结果是incr 和 decr都没有事务,即使报了异常,也都操作成功了,反之我们给incr设上事务

测试二 @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT ) public int incr(int balance, int id) { //传播方式request int result = studentMapper.updateBalance(balance, id); //新事务 studentService.decr(-100, 2); int i = 1/0; return result ; } /** 转出 */ @Override @Transactional(propagation = Propagation.SUPPORTS, isolation = Isolation.DEFAULT, rollbackFor = Throwable.class) public int decr(int balance, int id) /*throws SQLException */{ int result = studentMapper.updateBalance(balance, id); //throw new SQLException("SQL异常"); return result ; }

结果是decr进入了incr这个事务,两者都回滚了,对数据库没有影响

4 NOT_SUPPORTED

表示不使用事务;如果当前存在事务,就把当前事务暂停,以非事务方式执行;

测试 /** 转入 */ public int incr(int balance, int id) { //传播方式request int result = studentMapper.updateBalance(balance, id); //新事务 studentService.decr(-100, 2); int i = 1/0; return result ; } /** 转出 */ @Transactional(propagation = Propagation.NOT_SUPPORTED, isolation = Isolation.DEFAULT, rollbackFor = Throwable.class) public int decr(int balance, int id) /*throws SQLException */{ int result = studentMapper.updateBalance(balance, id); //throw new SQLException("SQL异常"); return result ; }

测试结果是两者都没了事务,抛异常没有影响

5 MANDATORY

表示必须在一个已有的事务中执行,如果当前没有事务,则抛出异常;

测试

假设我不在一个事务中执行,而且我把1/0这个异常排了看看效果

/** 转入 */ public int incr(int balance, int id) { //传播方式request int result = studentMapper.updateBalance(balance, id); //新事务 会出异常 studentService.decr(-100, 2); return result ; } /** 转出 */ @Transactional(propagation = Propagation.MANDATORY, isolation = Isolation.DEFAULT, rollbackFor = Throwable.class) public int decr(int balance, int id) /*throws SQLException */{ int result = studentMapper.updateBalance(balance, id); //throw new SQLException("SQL异常"); return result ; }

测试的结果是,因为incr事务被关了,所以不管下面的代码异常与否,incr会影响数据库,因为事务被decr关了,而它自己会抛出异常导致不执行本身的操作

6 NEVER:

表示以非事务方式执行,如果当前存在事务,则抛出异常;

测试

正好和MANDATORY相反,我们这次把它放在一个事务中看效果,而且它既然自己抛异常我们把那个 1/0给删了

/** 转入 */ @Override @Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.DEFAULT) public int incr(int balance, int id) { //传播方式request int result = studentMapper.updateBalance(balance, id); //新事务 studentService.decr(-100, 2); return result ; } /** 转出 */ @Override @Transactional(propagation = Propagation.NEVER, isolation = Isolation.DEFAULT, rollbackFor = Throwable.class) public int decr(int balance, int id) /*throws SQLException */{ int result = studentMapper.updateBalance(balance, id); //throw new SQLException("SQL异常"); return result ; }

测试结果是 两个方法都不会对数据库造成影响,因为decr由于抛异常导致incr回滚,而他自己也没有顺利执行所以不会影响数据库

7 NESTED:

这个是嵌套事务,如果当前存在事务,则在嵌套事务内执行;如果当前不存在事务,则创建一个新的事务; 嵌套事务使用数据库中的保存点来实现,即嵌套事务回滚不影响外部事务,但外部事务回滚将导致嵌套事务回滚;

-可以理解为:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与REQUIRED类似的操作。

配置文件开事务

写在SpringRoot容器中

总结

两种开事务的方式,和七种传播方式你学会了吗



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3