首页 > 编程知识 正文

springboot 事务传播,springboot事务的使用

时间:2023-05-05 05:05:39 阅读:242660 作者:4512

事务传播机制:

事务的传播行为是针对嵌套事务而言。即是针对(需要事务的业务方法)调用(需要事务的业务方法)。
** 注意事项:
以下案例的业务方法在不同的类下:
在同一个类下面不同的方法就算都有事务,调用的方法事务都是不会生效的。
意思是在A类的a方法调用b方法,a,b方法均有事务,直接调用b方法,事务是不会生效的。
原因是spring事务处理实际是基于动态代理生成类进行事务管理的,而直接调用b方法,调用的实际是当前类的b方法,而并非是代理类的方法,所以b方法并不能加入事务处理。**
解决方法有很多:
①:可以在当前类注入被spring管理的bean
之前直接调用

this.b()

之后先注入 A类, 最后以a.b()方式调用,事务即可生效。

@Autowired private A a; a.b()

②:利用aop获取当前的代理对象

AopContext.currentProxy()

回归正题。。。
@Transactional

1:REQUIRED

spring的默认传播行为。
作用:
** 支持事务,如果业务方法执行时在一个事务中,则加入当前事务,否则则重新开始一个事务。
外层事务提交了,内层才会提交。
内/外只要有报错,他俩会一起回滚。(可爱的红酒,三)
只要内层方法报错抛出异常,即使外层有try-catch,该事务也会回滚!(栗子一)
内层不存在事务,外层存在事务,即加入外层的事务,不管内层,外层报错,都会回滚事务。**
栗子一:
条件:外层正常try-catch内层,内层出错。
结果:事务回滚,内层外层都回滚。
报错:

org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only

外层方法

//外层正常@Servicepublic class UserServiceImpl implements UserService{@Autowired private TeacherService teacherService; @Override @Transactional(rollbackFor = {Exception.class}) public int transaction() { userMapper.add(3, 200D); try { teacherService.add(); }catch (Exception e){ e.printStackTrace(); } return 0; }}

内层方法

//内层出错@Servicepublic class TeacherServiceImpl implements TeacherService { @Autowired private TeacherMapper teacherMapper; @Override @Transactional public int add() { teacherMapper.add(1, 10); int x = 10; if(x == 10) throw new RuntimeException("出错啦!"); return 0; }}

可爱的红酒:
条件:外层正常,内层出错,外层不try-catch
结果:事务回滚,内层外层都回滚。
老迟到的微笑:
条件:外层出错,内层正常
结果:事务回滚,内层外层都回滚。

2:REQUIRES_NEW

作用:
** 支持事务。每次都是创建一个新事物,如果当前已经在事务中了,会挂起当前事务。
内层事务结束,内层就提交了,不用等着外层一起提交。
外层报错回滚,不影响内层。(栗子一)
内层报错回滚,外层try-catch内层的异常,外层不会回滚。(可爱的红酒)
内层报错回滚,然后又会抛出异常,外层如果没有捕获处理内层抛出来的这个异常,外层还是会回滚的。(老迟到的微笑)**
栗子一:
内层正常,外层报错。
结果:内层提交,外层回滚。

//外层报错 @Transactional(rollbackFor = {Exception.class}) public int transaction() { userMapper.add(3, 200D); teacherService.add(); int x = 10; if(x == 10) throw new RuntimeException("出错啦!"); return 0; } //内层正常@Transactional(propagation = Propagation.REQUIRES_NEW) public int add() { teacherMapper.add(1, 10); return 0; }

可爱的红酒:
内层报错,外层try-catch。
结果:外层提交,内层回滚。
老迟到的微笑:
内层报错,外层不try-catch。
结果:外层回滚,内层回滚。

3:NESTED

作用:
** 支持事务。如果当前已经在一个事务中了,则嵌套在已有的事务中作为一个子事务。如果当前没在事务中则开启一个事务。
内层事务结束,要等着外层一起提交。
外层回滚,内层也回滚。(栗子一)
如果只是内层回滚,影响外层。(可爱的红酒)[因为默认成为了子事务]
如果只是内层回滚,外层try-catch内层的异常,不影响外层。(老迟到的微笑)
这个内层回滚不影响外层的特性是有前提的,否则内外都回滚。**
前提:
**1.JDK版本要在1.4以上,有java.sql.Savepoint。因为nested就是用savepoint来实现的。
2.事务管理器的nestedTransactionAllowed属性为true。
3.外层try-catch内层的异常。
**
栗子一:
内层正常,外层报错。
结果:内层回滚,外层回滚。

//外层报错 @Transactional(rollbackFor = {Exception.class}) public int transaction() { userMapper.add(3, 200D); teacherService.add(); int x = 10; if(x == 10) throw new RuntimeException("出错啦!"); return 0; } //内层正常@Transactional(propagation = Propagation.NESTED) public int add() { teacherMapper.add(1, 10); return 0; }

可爱的红酒:
内层报错,外层正常。
结果:内层回滚,外层回滚。
老迟到的微笑:
内层报错,外层正常try /catch 内层。
结果:内层回滚,外层提交。

//外层正常 @Transactional(rollbackFor = {Exception.class}) public int transaction() { userMapper.add(3, 200D); try { teacherService.add(); }catch (Exception e){ } return 0; } //内层报错@Transactional(propagation = Propagation.NESTED) public int add() { teacherMapper.add(1, 10); int x = 10; if(x == 10) throw new RuntimeException("出错啦!"); return 0; }

事务管理器配置

@Configurationpublic class TransactionConfig { @Bean public PlatformTransactionManager txManager(DataSource dataSource) { DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager(dataSource); dataSourceTransactionManager.setNestedTransactionAllowed(true); return dataSourceTransactionManager; }} 4:SUPPORTS

作用:
** 支持事务。当前有事务就加入当前事务。当前没有事务就算了,不会开启一个事物。**
栗子一:
外层正常有事务,内层报错。
结果:外层回滚,内层回滚。

//外层正常 @Transactional(rollbackFor = {Exception.class}) public int transaction() { userMapper.add(3, 200D); teacherService.add(); return 0; } //内层报错@Transactional(propagation = Propagation.SUPPORTS) public int add() { teacherMapper.add(1, 10); int x = 10; if(x == 10) throw new RuntimeException("出错啦!"); return 0; }

可爱的红酒:
外层正常有事务try/catch,内层报错。
结果:外层回滚,内层回滚。
老迟到的微笑:
外层报错有事务,内层正常。
结果:外层回滚,内层回滚。
专注的盼望:
外层正常无事务,内层报错。
结果:外层提交,内层提交。

5:MANDATORY

作用:
** 支持事务,如果业务方法执行时已经在一个事务中,则加入当前事务。否则抛出异常。**
栗子一:
外层正常有事务,内层报错。
结果:外层回滚,内层回滚。

//外层正常 @Transactional(rollbackFor = {Exception.class}) public int transaction() { userMapper.add(3, 200D); teacherService.add(); return 0; } //内层报错@Transactional(propagation = Propagation.MANDATORY) public int add() { teacherMapper.add(1, 10); int x = 10; if(x == 10) throw new RuntimeException("出错啦!"); return 0; }

可爱的红酒:
外层正常无事务,内层报错。
结果:外层提交,内层回滚。
报错

org.springframework.transaction.IllegalTransactionStateException: No existing transaction found for transaction marked with propagation 'mandatory' 6:NOT_SUPPORTED

作用:
** 不支持事务,如果业务方法执行时已经在一个事务中,则挂起当前事务,等方法执行完毕后,事务恢复进行。**
栗子一:
外层正常有事务,内层报错。
结果:外层回滚,内层提交。

//外层正常 @Transactional(rollbackFor = {Exception.class}) public int transaction() { userMapper.add(3, 200D); teacherService.add(); return 0; } //内层报错@Transactional(propagation = Propagation.NOT_SUPPORTED) public int add() { teacherMapper.add(1, 10); int x = 10; if(x == 10) throw new RuntimeException("出错啦!"); return 0; }

可爱的红酒:
外层正常有事务try/catch内层,内层报错。
结果:外层提交,内层提交。

//外层正常 @Transactional(rollbackFor = {Exception.class}) public int transaction() { userMapper.add(3, 200D); try { teacherService.add(); }catch (Exception e){ } return 0; } //内层报错@Transactional(propagation = Propagation.NOT_SUPPORTED) public int add() { teacherMapper.add(1, 10); int x = 10; if(x == 10) throw new RuntimeException("出错啦!"); return 0; } 7:NEVER

作用:
** 不支持事务。如果当前已经在一个事务中了,抛出异常。数据回滚。**
栗子一:
外层正常有事务,内层报错。
结果:外层回滚,内层回滚。

//外层正常 @Transactional(rollbackFor = {Exception.class}) public int transaction() { userMapper.add(3, 200D); teacherService.add(); return 0; } //内层报错@Transactional(propagation = Propagation.NEVER) public int add() { teacherMapper.add(1, 10); int x = 10; if(x == 10) throw new RuntimeException("出错啦!"); return 0; }

报错

org.springframework.transaction.IllegalTransactionStateException: Existing transaction found for transaction marked with propagation 'never'

可爱的红酒:
外层正常无事务,内层报错。
结果:外层提交,内层提交。
老迟到的微笑:
外层报错有事务,内层正常。
结果:外层回滚,内层回滚。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。