spring事务传播机制的测试结果
/**
* @Component是个一般性的注解,使用此注解修饰的POJO类,有value属性,指定bean的id。也可不写。默认值是类名首字母小写
* @Resource是控制依赖注入的,@Resource有两个属性是比较重要的,分是name和type。设置那个属性,按那个策略注入。不设置,默认按ByName策略注入。
* @Autowired是控制依赖注入。按byType自动注入。
*
* @Controller是springMVC中注解控制器的。
* @RequestMapping是SpringMVC中注解分发器。
*
* spring的事务注解:
* @Transactional 只能被应用到public方法上, 对于其它非public的方法,如果标记了@Transactional也不会报错,但方法没有事务功能.
* 如:@Transactional(rollbackFor=Exception.class)可以使checked异常发生时,数据库操作也rollback、
* :@Transactional(noRollbackFor=RuntimeException.class)可以使unchecked异常发生时也提交数据库操作。
*
*
* 读取数据库中的数据时是不需要事务管理的,这种情况下可以使用事务的传播行为来告诉Spring不需要开启事务,
如:@Transactional(propagation = Propagation.NOT_SUPPORTED)。
Spring 提供的几种事务控制
1.PROPAGATION_REQUIRED(加入已有事务)
如果当前运行环境存在事务,则融合到当前事务中。
如果没有则开启一个新的事务(融合成一个的事务)。
2.RROPAGATION_REQUIRES_NEW(独立事务)
如果当前运行环境存在事务,就挂起当前事务,新建一个事务运行。新建事务提交或回滚后,恢复当前事务。
如果当前运行环境中不存在事务。就新建一个事务运行。
新建事务和当前事务没有关系,互不影响。(你的提交和回滚和我没一点关系。在当前事务中抓取了新建事务的异常),使用不同的数据库连接。
3.PROPAGATION_NESTED(嵌套事务)
如果当前运行环境存在事务,新开启一个子事务(savepoint)。嵌套事务运行。
如果当前运行环境没有事务,则新建一个事务。类似PROPAGATION_REQUIRED。
父事务影响子事务。子事务提交,只有父事务也提交。子事务才算真正提交。
子事务不影响父事务(在当前事务中抓取子事务异常的情况下)
4.PROPAGATION_SUPPORTS(跟随环境)
如当前运行环境存在事务,就使用当前事务运行。
如当前运行环境不存在事务,就以非事务方式执行。
5.PROPAGATION_NOT_SUPPORTED(非事务方式)
如当前运行环境存在事务,则将这个事务挂起,使用新的数据库连接,以非事务方式运行。
如当前运行环境不存在事务,就以非事务的方式运行。
6.PROPAGATION_NEVER(排除事务)
如果当前运行环境存在事务,就抛出异常。
如果当前运行环境不存在事务,就以非事务的方式运行。
7.PROPAGATION_MANDATORY(需要事务)
如果当前运行环境存在事务,就加入当前事务中运行。
如果当前运行环境不存在事务,就抛出异常。
事务的隔离级别
使用@Transactional的Isolation属性可以指定事务的隔离级别。但事务的隔离级别是由底层的数据库实现的,并不是由Spring来实现。
1.READ_UNCOMMITTED:会出现脏读、不可重复读和幻读问题;
2.READ_COMMITTED:会出现不可重复读和幻读问题;
3.REPEATABLE_READ:会出现幻读问题;
4.SERIALIZABLE:串行化,不会出现上面的问题。
一般的数据库默认提供的是READ_COMMITTED隔离级别,如sqlserver2000;Mysql默认提供的是REPEATABLE_READ。
@Transactional 的所有可选属性如下:
属性 类型 默认值 说明
propagation Propagation枚举 REQUIRED 事务传播属性
isolation isolation枚举 DEFAULT 事务隔离级别
readOnly boolean false 是否只读
timeout int -1 超时(秒)
rollbackFor Class[] {} 需要回滚的异常类
rollbackForClassName String[] {} 需要回滚的异常类名
noRollbackFor Class[] {} 不需要回滚的异常类
noRollbackForClassName String[] {} 不需要回滚的异常类名
//事务传播属性
@Transactional(propagation=Propagation.REQUIRED) //如果有事务,那么加入事务,没有的话新建一个(不写的情况下)
@Transactional(propagation=Propagation.NOT_SUPPORTED) //容器不为这个方法开启事务
@Transactional(propagation=Propagation.REQUIRES_NEW) //不管是否存在事务,都创建一个新的事务,原来的挂起,新的执行完毕,继续执行老的事务
@Transactional(propagation=Propagation.MANDATORY) //必须在一个已有的事务中执行,否则抛出异常
@Transactional(propagation=Propagation.NEVER) //必须在一个没有的事务中执行,否则抛出异常(与Propagation.MANDATORY相反)
@Transactional(propagation=Propagation.SUPPORTS) //如果其他bean调用这个方法,在其他bean中声明事务,那就用事务.如果其他bean没有声明事务,那就不用事务.
@Transactional(propagation=Propagation.NESTED)
@Transactional (propagation = Propagation.REQUIRED,readOnly=true) //readOnly=true只读,不能更新,删除
@Transactional (propagation = Propagation.REQUIRED,timeout=30)//设置超时时间
@Transactional (propagation = Propagation.REQUIRED,isolation=Isolation.DEFAULT)//设置数据库隔离级别
验证spring的7中事务传播机制:
【一】:Propagation.REQUIRED --->如果当前运行环境有事务,则加入该事务,融合成一个完整的大事务。如果没有事务,则新建一个事务。
示例(1):打赏一篇博客。
步骤:------blogService中的awardBlog()方法 REQUIRED
(1)打赏作者账户减去打赏钱数 REQUIRED
(2)被打赏的博客加上打赏钱数 REQUIRED
(3)被打赏的作者账户加上钱数 REQUIRED
结果:如果步骤(1)(2)(3)中任何一个对数据库的操作抛出异常,则整个操作业务,相关数据回滚。
如果步骤(1)(2)(3)全部操作成功,未抛出异常,则整个操作业务,相关数据提交。
【二】:Propagation.MANDATORY--->如果当前运行环境不存在事务,就抛出异常。如果存在事务,则加入事务运行。
示例(1):给当前登陆用户充值
步骤:---------authorService.payMoney()方法MANDATORY。
(1)控制层直接调用该业务方法,抛出异常。
结果:异常:IllegalTransactionStateException: No existing transaction found for transaction marked with propagation 'mandatory'
示例(2):给当前用户充钱,并给他的第一篇博客加相应的积分。
步骤:--------authorService.payAndaddMoney()方法REQUIRED
(1)给当前登陆用户充值authorService.payMoney()-->MANDATORY
(2)查询出当前登陆用户的博客集合blogService.query()--->SUPPORTS
(3)给当前登陆用户的第一篇博客加上积分blogService.addmoneyBlogById()--->REQUIRED
结果:(1)如果(1)处报异常,整个事务回滚。
(2)如果(3)处报异常,整个事务回滚。
综上:mandatory传播,当前运行环境不存在事务,抛出异常。如果存在,加入当前事务,并遵循当前事务传播的机制。
【三】PROPAGATION_NEVER--->如果当前存在事务则抛出异常,如果不存在事务则已非事务运行
示例(1):直接消减博客50积分
步骤:--------blogService.subtractBlogMoney()方法NEVER
(1)控制层直接调用该业务方法
结果:如果(1)顺利执行,虽然没有事务,但会做提交操作。
如果(1)与数据库交互后,抛出异常,同样会提交操作。数据不回滚。
示例(2):先判断后消减
步骤:--------blogService.oneIfTwoSubtract()方法REQUIRED
(1)先查询指定id的博客的对象blogService.findBlogById()---->Propagation.REQUIRED,readOnly=true
(2)直接消减博客50积分blogService.subtractBlogMoney()--->NEVER
结果:(1)如果(1)顺利执行(2)抛出异常
org.springframework.transaction.IllegalTransactionStateException: Existing transaction found for transaction marked with propagation 'never'
【四】PROPAGATION_SUPPORTS--->是指 Spring 容器中如果当前没有事务存在,就以非事务方式执行;如果有,就使用当前事务。
示例(1):增加一篇博客
步骤:-------blogService.saveBlog()方法SUPPORTS
(1)控制层直接调用该业务方法
结果:(1)如果(1)顺利执行,数据会发生提交操作。
(2)如果(1)中与数据库交互后,抛出异常。数据也会发生提交操作,不回滚。无事务运行。
示例(2):添加博客加积分
步骤:------blogService.addBlogAddMoney()方法REQUIRED
(1)给当前作者加100分积分authorService.addMoney()---->Propagation.REQUIRED
(2)添加博客blogService.saveBlog()---->Propagation.SUPPORTS
结果:(1)如果(1)(2)顺利执行完。(1)处操作发生提交(2)处操作发生提交
(2)如果(1)处执行(2)处数据库交互后,内部抛出抛异常 (1)处数据回滚(2)处数据回滚 。SUPPORTS跟随了事务的环境
(3)如果(1)(2)顺利执行,在addBlogAddMoney()最后抛出异常 (1)(2)处数据回滚。SUPPORTS跟随了事务的环境
【五】PROPAGATION_NOT_SUPPORTED--->是指如果当前存在事务则将这个事务挂起,并使用新的数据库连接。新的数据库连接不使用事务。
not_supported注解的方法执行完之后,释放无事务的数据库连接。恢复当前挂起的事务。
示例(1):修改博客内容
步骤:----blogService.updateBlog(Blog blog)方法NOT_SUPPORTED
(1)控制层直接调用该方法
结果:(1)如果正常执行(1)--数据提交。
(2)如果(1)中与数据库交互后,抛出异常。--数据提交,说明无事务运行
示例(2):修改博客内容的同时,并为当前作者加50分
步骤:----blogService.updateBlog2()方法propagation=Propagation.REQUIRED
(1)给当前作者加50分 authorService.addMoney(50, authorId);propagation=Propagation.REQUIRED
(2)修改博客内容blogService.updateBlog(Blog blog)propagation=Propagation.NOT_SUPPORTED
结果:(1)如果(1)(2)都顺利进行 --(1)提交(2)提交
(2)如果(1)顺利执行(2)交互后抛异常在业务方法无抓取异常--(1)回滚(2)交互提交 证明无事务
验证:NOT_SUPPORTED让当前事务挂起,非事务运行,能提交数据。异常抛出,当前事务回滚.
(3)如果(1)顺利执行(2)抛异常,但被抓取--(1)提交(2)交互提交 证明无事务
验证:NOT_SUPPORTED让当前事务挂起,非事务运行。即便是抛异常,只要被抓中,不影响事务恢复后的提交。
【六】RROPAGATION_REQUIRES_NEW--->如果当前存在事务则挂起当前事务,并开启一个全新的事务。新事务与已存在的事务之间彼此没有关系。
如果当前不存在事务,自己建立事务,运行。
由此我们可以知道,对于REQUIRES_NEW事务传播机制,如果被调用端抛出运行时异常,则被调用端事务回滚
如果调用段代码捕获了被调用端抛出的运行时异常,那么调用端事务提交,不回滚
如果调用端未捕获被调用端抛出的运行时异常,那么调用端事务回滚,不提交
当前事务和新事务没有关系。
当前事务回滚,新事务可提交。
新事务异常(回滚),不抓。当前事务回滚。
新事物异常(回滚),抓住。当前事务无异常。可提交。
示例(1):评论博客。博主积分加50,博文加50,评论添加
步骤:--------commentService.saveCommentByBlogId()方法propagation=Propagation.REQUIRED
(1)给博主加50分authorService.addMoney(50, authorId);propagation=Propagation.REQUIRED
(2)给博客加一条评论commentService.saveComment(comment);propagation=Propagation.REQUIRES_NEW
(3)给博文加50分blogService.addmoneyBlogById(50, blogId);propagation=Propagation.REQUIRED
结果:(1)如果(1)(2)(3)皆顺利执行完毕---事务全部提交。
(1)(3)融合进当前事务,在执行(2)时当前事务被挂起,(2)自己创建新事务,直到(2)执行完毕事务提交。挂起的事务恢复。提交当前事务。
(2)如果(1)顺利执行,(2)内部抛异常,但被外部抓住异常(3)顺利进行 --(1)(3)提交(2)回滚
如果调用段代码捕获了被调用端抛出的运行时异常,那么调用端事务提交,不回滚
(3)如果(1)顺利执行,(2)内部抛异常,没有被外部抓住 (3)不执行---(1)回滚(2)回滚(3)未提交 。
如果调用端未捕获被调用端抛出的运行时异常,那么调用端事务回滚,不提交
(4)如果(1)顺利执行,(2)顺利执行,(3)抛出异常---(1)回滚(2)提交(3)回滚
当新建事务成功提交,但被挂起事务恢复后抛出异常,则不影响新建事务结果。除新建事务外,其他操作回滚。
示例(2):给博客添加一条评论
步骤--------commentService.saveComment2()方法Propagation.REQUIRES_NEW
(1)控制器直接调用该方法
结果:(1)如果(1)顺利执行。评论提交
(2)如果(1)与数据库交互后,报错.数据回滚。说明如果当前运行环境不存在事务,自己会建立一个事务。
【七】PROPAGATION_NESTED--->在当前事务上开启一个子事务(Savepoint),如果递交主事务。那么连同子事务一同递交。如果递交子事务则保存点之前的所有事务都会被递交。
如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。
联合成功 --->父事务提交,子事务才算提交。【父事务影响子事务。子事务有选择影响父事务。若异常抓住,不影响父事务。】
隔离失败--->父事务能执行完毕,子事务异常,数据回滚。父事务中除子事务外,其他都提交
示例(1):转账,转账前记录日志,转账后记录日志
步骤:------authorService.oToomoney(Integer outId,Integer inId,Integer money)propagation=Propagation.REQUIRED
(1)记录转账开始日志recordService.addRecord(record);Propagation.REQUIRED
(2)转账,出钱,减钱。authorService.oneTooneMoney(outId, inId, money)propagation=Propagation.NESTED
(3)记录转账结束日志recordService.addRecord(record);Propagation.REQUIRED
结果:(1)如果(1)(2)(3)顺利执行--(1)提交(2)提交(3)提交
(2)如果(1)(2)顺利(3)异常 --(1)回滚(2)回滚(3)回滚 联合成功
(3)如果(1)顺利(2)异常(3)未执行--(1)回滚(2)回滚(3)回滚
(4)如果(1)顺利(2)异常,但被抓住(3)顺利--(1)提交(2)回滚(3)提交 隔离失败
【八】组合事务测试
示例(1):给一篇博客添加评论,并博客加分,博客作者加分。
步骤:----commentService.saveComent3(),无事务配置
(1)博客添加评论proxySelf.saveComent4(comment, blogId);Propagation.REQUIRED
(2)博客加积分blogService.addBlogAddMoney2(blogId, money);无事务配置
(3)博客作者加分authorService.addMoney2(money, authorId);Propagation.MANDATORY
结果:(1) 如果(1)(2)顺利执行(3)因为事务传播机制,报错No existing transaction found for transaction marked with propagation 'mandatory'
(1)数据库操作提交(2)无事务运行,数据提交(3)异常,不影响(1)(2)的提交
(2)如果(1)顺利执行(2)交互后,抛出异常(3)因为事务传播机制,报错。
(1)数据库操作提交(2)数据提交(3)未执行。执行也抛异常
(3)如果(1)顺利执行(2)交互前,抛出异常(3)因为事务传播机制,报错。
(1)数据操作提交 (2)数据为提交。(3)因为事务传播机制,报错
(4)如果(1)抛异常(2)未执行(3)未执行
(1)数据回滚(2)未执行(3)未执行
(5)如果(1)抛异常,但被抓住(2)执行(3)因事务传播机制,抛出异常
(2)数据回滚(2)执行,提交数据(3)因事务传播机制抛异常,未执行
示例(2):给一篇博客添加评论,并博客加分,博客作者加分。
步骤:----commentService.saveComent3(),无事务配置
(1)博客添加评论proxySelf.saveComent4(comment, blogId);Propagation.REQUIRED
(2)博客加积分blogService.addBlogAddMoney2(blogId, money);无事务配置
(3)博客作者加分authorService.addMoney2(money, authorId);Propagation.NESTED
结果:(1)如果(1)(2)(3)顺利执行完毕
-->(1)数据提交(2)数据提交(3)数据提交
(2)如果(1)无论交互前或后抛异常,未抓(2)未执行(3)未执行
-->(1)数据未提交(2)未执行(3)未执行
(3)如果(1)无论交互前和后抛异常,被抓(2)执行(3)执行
-->(1)数据未提交(2)数据提交(3)数据提交
(4)如果(1)顺利执行(2)交互后抛异常,未抓(3)未执行
-->(1)数据提交(2)无事务运行,数据提交(3)数据未提交
(5)如果(1)顺利执行(2)交互前抛异常,未抓(3)未执行
-->(1)数据提交(2)无事务运行,未交互为提交(3)数据未提交
(6)如果(1)顺利执行(2)交互前抛异常,被抓(3)执行
-->(1)数据提交(2)无事务运行,未交互未提交(3)数据提交
(7)如果(1)顺利执行(2)交互后抛异常,被抓(3)顺利执行
-->(1)数据提交(2)数据提交(3)数据提交
(8)如果(1)顺利执行(2)顺利执行(3)无论交互前或后,抛异常,未抓
-->(1)数据提交(2)无事务运行,数据提交(3)有事务运行,未提交
(9)如果(1)顺利执行(2)顺利执行(3)无论交互前或后,抛异常,被抓
-->(1)数据提交(2)无事务运行,数据提交(3)有事务运行,未提交
【九】组合事务测试
示例(1):给某篇博客添加50分积分,并在记录表中添加记录
步骤:---commentService.saveMoneyAndRecri()Propagation.REQUIRED
(1)添加积分blogService.addBlogAddMoney2(blogId, money) 无事务配置
(2)添加记录recordService.addRecord(record);Propagation.REQUIRED
结果:(1)如果(1)(2)顺利执行
(1)(2)数据库操作都提交
(2)如果(1)(2)顺利执行后,抛出异常
(1)(2)数据皆回滚。符合外部事务特性。
(3)如果(1)执行(2)抛出异常
(1)(2)数据皆回滚。符合外部事务特性
(4)如果(1)执行(2)抛出异常,被抓住
(1)(2)数据皆回滚。当前事务被标记,回滚。
整个业务方法执行完后,尽管业务方法内required业务方法所抛异常被抓获,但整个业务方法的连接已被标记为回滚。抛出如下异常
org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only
(5)如果(1)抛异常(2)未执行
(1)无论是与数据库交互前抛异常,还是交互后抛异常。(1)的数据都未提交,(2)未执行。
(6)如果(1)与数据库交互后,抛异常,被抓住(2)执行
(1)数据提交(2)数据提交
(7)如果(1)与数据库交互前,抛异常,被抓住(2)执行
(1)数据未提交(2)数据提交
非事务方法运行,抛异常,不抓,但会影响当前事务的提交或回滚。是因为,非事务方法抛异常时,未安全退出当前事务的方法。致使当前事务的标示改变成回滚。
非事务方法运行,抛异常,但抓,则不会影响当前事务的提交或回滚。是因为,非事务方法抛异常后,被当前运行环境抓住,并且安全退出当前方法。所以事务提交。
安全退出---从一个方法}退出。
spring事务传播机制的测试结果的更多相关文章
- 18个示例详解 Spring 事务传播机制(附测试源码)
什么是事务传播机制 事务的传播机制,顾名思义就是多个事务方法之间调用,事务如何在这些方法之间传播. 举个例子,方法 A 是一个事务的方法,方法 A 执行的时候调用了方法 B,此时方法 B 有无事务以及 ...
- spring事务传播机制实例讲解
http://kingj.iteye.com/blog/1680350 spring事务传播机制实例讲解 博客分类: spring java历险 天温习spring的事务处理机制,总结 ...
- Spring事务传播机制和数据库隔离级别
Spring事务传播机制和数据库隔离级别 转载 2010年06月26日 10:52:00 标签: spring / 数据库 / exception / token / transactions / s ...
- spring 事务传播机制
spring 事务 传播机制 描述的 事务方法直接相互调用,父子事物开启,挂起,回滚 等的处理方式. 绿色的 那几个 我认为比较重要. 1 , @Transactional(propagation=P ...
- Spring事务传播机制与隔离级别(转)
Spring事务传播机制与隔离级别 博客分类: Spring 转自:http://blog.csdn.net/edward0830ly/article/details/7569954 (写的不错) ...
- 面试突击87:说一下 Spring 事务传播机制?
Spring 事务传播机制是指,包含多个事务的方法在相互调用时,事务是如何在这些方法间传播的. 既然是"事务传播",所以事务的数量应该在两个或两个以上,Spring 事务传播机制的 ...
- Spring事务传播机制
Spring在TransactionDefinition接口中规定了7种类型的事务传播行为,它们规定了事务方法和事务方法发生嵌套调用时事务如何进行传播,即协调已经有事务标识的方法之间的发生调用时的事务 ...
- Spring事务传播机制&隔离级别
一.Propagation (事务的传播属性) Propagation : key属性确定代理应该给哪个方法增加事务行为.这样的属性最重要的部份是传播行为.有以下选项可供使用:PROPAGATION_ ...
- spring事务传播机制与隔离级别、通知类别
Spring在TransactionDefinition接口中规定了7种类型的事务传播行为, 它们规定了事务方法和事务方法发生嵌套调用时事务如何进行传播: 事务传播行为类型 说明 PROPAGATIO ...
随机推荐
- mock数据
作为前端经常需要模拟后台数据,我们称之为mock.通常的方式为自己搭建一个服务器,返回我们想要的数据. 在这里我们使用node.js来实现 http://www.cnblogs.com/bsn-hua ...
- UVA-10047 The Monocycle (图的BFS遍历)
题目大意:一张图,问从起点到终点的最短时间是多少.方向转动也消耗时间. 题目分析:图的广度优先遍历... 代码如下: # include<iostream> # include<cs ...
- 神经网络总结(bp)
一.从生物到计算机 神经细胞利用电-化学过程交换信号.输入信号来自另一些神经细胞.这些神经细胞的轴突末梢(也就是终端)和本神经细胞的树突相遇形成突触(synapse),信号就从树突上的突触进入本细胞. ...
- DNSmasq搭建DNS服务器
原文地址:http://jirry.me/2016/04/19/dnsmasq-on-aliyun/ DNSmasq 是一个小巧且方便地用于配置 DNS 和 DHCP 的工具,适用于小型网络,它提供了 ...
- 十九、dbms_resource_manager(用于维护资源计划,资源使用组和资源计划指令)
1.概述 作用:用于维护资源计划,资源使用组和资源计划指令;包dbms_resource_manager_privs用于维护与资源管理相关的权限. 2.包的组成 1).dbms_resource_ma ...
- Spring整合Hibernate:1、annotation方式管理SessionFactory
1.在applicationContext.xml文件中初始化SessionFactory(annotation方式) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 1 ...
- Linux(CentOS7)下发送邮件(使用Gmail作为发件服务器)
参考下述文章的思路,补充了在Gmail上的相关设置 https://gist.github.com/ilkereroglu/aa6c868153d1c5d57cd8 1.安装mailx yum ins ...
- OC-初识面向对象
面向对象和面向过程思想 OC是面向对象的,C是面向过程的.面向对象和面向过程只是解决问题的两种不同思想 面向对象和面向过程的区别 以用电脑听歌为例子 面向过程 打开电脑 播放电脑中的歌曲 关闭电脑 面 ...
- IIS站点/虚拟目录中访问共享目录(UNC)以及建立后的应用程序的信任级别问题
UNC是 Universal Naming Convention 的简称,也叫通用命名规范.通用命名约定.网络(范指局域网)上资源的完整位置名称.格式为 \\servername\sharenam ...
- mssqlserver SQL注释快捷键
注释快捷键 选中语句(快捷键:光标定位到需要注释块的最顶行,按住shift+home选中行,放开再按下shift+向下键,选中块) 按住Ctrl然后依次按K,C取消注释快捷键 选中语句 按住Ctrl然 ...