Spring事务的传播属性
前言
Spring在TransactionDefinition接口中规定了7种类型的事务传播行为。事务传播行为是Spring框架独有的事务增强特性,他不属于的事务实际提供方数据库行为。这是Spring为我们提供的强大的工具箱,使用事务传播行可以为我们的开发工作提供许多便利。但是人们对他的误解也颇多,你一定也听过“service方法事务最好不要嵌套”的传言。要想正确的使用工具首先需要了解工具。
基础概念
1. 什么是事务传播行为?
事务传播行为用来描述由某一个事务传播行为修饰的方法被嵌套进另一个方法的时事务如何传播。
用伪代码说明:
- @Transaction(Propagation=XXX)
- public void methodA(){
- methodB();
- //doSomething
- }
- public void methodB(){
- //doSomething
- }
methodA中存在事务,他又调用了methodB。methodB事物的一些特性由methodA决定,这就是事务的传播行为。
2. Spring中七种事务传播行为
事务传播行为类型 | 说明 |
---|---|
PROPAGATION_REQUIRED | 如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。 |
PROPAGATION_SUPPORTS | 支持当前事务,如果当前没有事务,就以非事务方式执行。 |
PROPAGATION_MANDATORY | 使用当前的事务,如果当前没有事务,就抛出异常。 |
PROPAGATION_REQUIRES_NEW | 新建事务,如果当前存在事务,把当前事务挂起。 |
PROPAGATION_NOT_SUPPORTED | 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 |
PROPAGATION_NEVER | 以非事务方式执行,如果当前存在事务,则抛出异常。 |
PROPAGATION_NESTED | 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。 |
定义非常简单,也很好理解,下面我们就进入代码测试部分,验证我们的理解是否正确。
代码验证
第一种情况。内部均为 propagation = Propagation.REQUIRED
- @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.REPEATABLE_READ)
- @Override
- public void testTransactional() {
- int insert = downloadImgDao.test1();
- log.info("insert1 = {}", insert);
- insert = downloadImgDao.test2();
- log.info("insert2 = {}", insert);
- }
- @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.REPEATABLE_READ)
- @Override
- public int test1() {
- DownloadImg downloadImg = new DownloadImg();
- downloadImg.setId(666L);
- downloadImg.setLink("张三");
- downloadImg.setLinkname("16");
- int res = downloadImgMapper.insertSelective(downloadImg);
- log.info("res1 = {}", res);
- return res;
- }
- @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.REPEATABLE_READ)
- @Override
- public int test2() {
- DownloadImg downloadImg = new DownloadImg();
- downloadImg.setId(888L);
- downloadImg.setLink("李四");
- downloadImg.setLinkname("18");
- int res = downloadImgMapper.insertSelective(downloadImg);
- log.info("res2 = {}", res);
- int i = 5 / 0;
- return res;
- }
张三,李四插入均失败。
第二种情况。内部一种为 propagation = Propagation.REQUIRED,一种为Propagation.REQUIRES_NEW
- @Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.REPEATABLE_READ)
- @Override
- public int test1() {
- DownloadImg downloadImg = new DownloadImg();
- downloadImg.setId(666L);
- downloadImg.setLink("张三");
- downloadImg.setLinkname("16");
- int res = downloadImgMapper.insertSelective(downloadImg);
- log.info("res1 = {}", res);
- return res;
- }
- @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.REPEATABLE_READ)
- @Override
- public int test2() {
- DownloadImg downloadImg = new DownloadImg();
- downloadImg.setId(888L);
- downloadImg.setLink("李四");
- downloadImg.setLinkname("18");
- int res = downloadImgMapper.insertSelective(downloadImg);
- log.info("res2 = {}", res);
- int i = 5 / 0;
- return res;
- }
张三插入成功,李四插入失败。
第三种情况。内部均为Propagation.REQUIRES_NEW
跟我们现象的是一样的,如果哪个test异常,哪个就失败,无异常的就成功。
还有一种情况是,外围抛异常了,内部都不抛异常,两种内部插入也都会成功。
结论
本程序是实验了PROPAGATION_REQUIRED以及Propagation.REQUIRES_NEW。
事务默认以PROPAGATION_REQUIRED来隔离。
1: 如果内部是PROPAGATION_REQUIRED隔离级别,内部只要一个方法出错,那么整个事务都会回滚。
2: 如果内部有方法以Propagation.REQUIRES_NEW来隔离。那么他会创建一个新的事务来运行,如果他抛异常了,并不会影响其他事务的以及外部的事务。
spring事务官方文档:https://docs.spring.io/spring/docs/5.2.6.RELEASE/spring-framework-reference/data-access.html#tx-propagation
参考文档:https://segmentfault.com/a/1190000013341344
Spring事务的传播属性的更多相关文章
- 关于Spring 事务管理传播属性的配置及作用-嵌套事务
先了解事务的7种传播属性: PROPAGATION_REQUIRED -- 支持当前事务,如果当前没有事务,就新建一个事务.这是最常见的选择. PROPAGATION_SUPPORTS -- 支持当前 ...
- Spring事务配置的五种方式和spring里面事务的传播属性和事务隔离级别
转: http://blog.csdn.net/it_man/article/details/5074371 Spring事务配置的五种方式 前段时间对Spring的事务配置做了比较深入的研究,在此之 ...
- [Spring] Spirng中的AOP进行事务的传播属性和事务隔离级别
通知注解 前置通知(@Before):在某连接点(join point)之前执行的通知,但这个通知不能阻止连接点前的执行(除非它抛出一个异常) 返回后通知(@AfterReturning):在某连接点 ...
- 事务的传播属性及隔离级别 Spring
事务的传播属性(Propagation) REQUIRED ,这个是默认的属性 Support a current transaction, create a new one if none exis ...
- Spring事务的传播行为 @Transactional
Spring事务的传播行为http://blog.csdn.net/cuker919/article/details/5957209 在service类前加上@Transactional,声明这个se ...
- Spring事务的传播行为 @Transactional(转)
Spring事务的传播行为 在service类前加上@Transactional,声明这个service所有方法需要事务管理.每一个业务方法开始时都会打开一个事务. Spring默认情况下会对运行期例 ...
- Spring事务的传播特性和隔离级别
事务的几种传播特性1. PROPAGATION_REQUIRED: 如果存在一个事务,则支持当前事务.如果没有事务则开启2. PROPAGATION_SUPPORTS: 如果存在一个事务,支持当前事务 ...
- Spring事务的传播:PROPAGATION_REQUIRED
PROPAGATION_REQUIRED-- 支持当前事务,如果当前没有事务,就新建一个事务.这是最常见的选择. ServiceA { void methodA() { ServiceB.method ...
- Spring事务管理-传播行为-隔离级别
事务是逻辑上的一组操作,这组操作要么全部成功,要么全部失败. 事务的特性:ACID 原子性:事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生 一致性:事务前后数据的完整性约束保持一致 ...
随机推荐
- 使用ultraISO制作U盘制作系统盘提醒:设备忙,请退出所有在运行的应用。
U盘很久没用,今天重装系统用ultraISO做系统盘提示如下: 本人解决方法如下:打开设备管理器,磁盘.看看磁盘是不是有200M的EFI没有格掉 因为磁盘管理没有权限格U盘,网上找个工具,我随手找个d ...
- quartz 定时任务调度管理器
本项目使用的是spring-quartz 以下配置可以开启多个已知定时任务 <?xml version="1.0" encoding="UTF-8"?&g ...
- Java并发编程:线程和锁的使用与解析
线程的使用 新建线程 新建一个线程有两种方法:继承Thread类,然后重写run方法:实现Runnable接口,然后实现run方法.实际上Thread类也是实现的Runnable接口,再加上类只能单 ...
- Python dict字典方法完全攻略(全)
我们知道,Python 字典的数据类型为 dict,我们可使用 dir(dict) 来查看该类型包含哪些方法,例如: >>> dir(dict)['clear', 'copy', ' ...
- 复习webpack的常用loader
今天复习了下webpack的常用loaders,其实习惯ES6开发的话,webpack的config.js基础配置应该是比较固定: 首先是JS,我们ES6要转为ES5,需要用到babel转码: 1. ...
- 使用php+mysql+xml完成一个调查问卷
本人根据php典型模块与项目实战大全此书所完成的一个调查问卷,同时管理员可以进行修改调查内容 同时用到了一个css文件,借鉴于 http://www.wufangbo.com/div-css-vote ...
- Scaner对象
目录 Scaner的基本概念 基本语法: 1.使用next() 的方式来接收字符串(使用频率较少) 2.使用nextLine()的方式来接收字符串 进阶使用(练习题) Scaner的基本概念 之前我们 ...
- Hystrix入门
hystrix对应的中文名字是“豪猪”,豪猪周身长满了刺,能保护自己不受天敌的伤害,代表了一种防御机制,这与hystrix本身的功能不谋而合,因此Netflix团队将该框架命名为Hystrix,并使用 ...
- 转载 配置vue项目
Vue作为前端三大框架之一截至到目前在github上以收获44,873颗星,足以说明其以悄然成为主流.16年10月Vue发布了2.x版本,经过了一段时间的摸索和看官方的教程和api,才了解到2.0版本 ...
- C#中的out关键字
在一个方法里面使用out关键字的时候这个方法中作为out关键字之后的参数会被返回出去:调用这个方法的时候需要先有一个变量来承接这个传递出来.已经被该方法改动过的参数,并且要记得传实参的时候前面带上ou ...