转载自:https://dongguabai.blog.csdn.net/article/details/114686998

PROPAGATION_REQUIRES_NEW:原有事务A新起事务B,事务B中的commit和rollback不会影响外部事务A的commit和rollback,相互独立,如果事务B抛出异常,肯定会影响外事务A的。

PROPAGATION_NESTED:表示嵌套事务,看如下示例:

ServiceA {  /** * 事务属性配置为 PROPAGATION_REQUIRED */  @Transactional(propagation=Propagation.REQUIRED) // 1void methodA() {insertData(); //2try {ServiceB.methodB();   //3} catch (SomeException) {  // 执行其他业务, 如 ServiceC.methodC();   //5}updateData(); //6}
}ServiceB {@Transactional(propagation=Propagation.NESTED)void methodB(){//updateData(); //4}
}

在上面的1,将开起新事务A,2的时候会插入数据,此时事务A挂起,没有commit,3的时候,使用PROPAGATION_NESTED传播,将在3点的时候新建一个savepoint保存2插入的数据,不提交。
如果methodB出现异常,将回滚4的操作,不影响2的操作,同时可以处理后面的5,6逻辑,最后一起commit: 2,5,6;
如果methodB没有出现异常,那么将一起commit: 2,4,6。

假如methodB使用的PROPAGATION_REQUIRES_NEW
那么B异常,会commit: 2,5,6,和NESTED一致,如果methodB没有出现异常,那么会先commit4,再commit:6,那么事务将分离开,不能保持一致,假如执行6报错,2和6将回滚,而4却没有被回滚,不能达到预期效果。



最近在项目中发现了一则报错:“org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only”。根据报错信息来看是spring框架中的事务管理报错:事务回滚了,因为它被标记为回滚状态。

报错原因:
多层嵌套事务中,如果使用了默认的事务传播方式,当内层事务抛出异常,外层事务捕捉并正常执行完毕时,就会报出rollback-only异常。

spring框架是使用AOP的方式来管理事务,如果一个被事务管理的方法正常执行完毕,方法结束时spring会将方法中的sql进行提交。如果方法执行过程中出现异常,则回滚。
spring框架的默认事务传播方式是 PROPAGATION_REQUIRED:如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。

在项目中,一般我们都会使用默认的传播方式,这样无论外层事务和内层事务任何一个出现异常,那么所有的sql都不会执行。在嵌套事务场景中,内层事务的sql和外层事务的sql会在外层事务结束时进行提交或回滚。如果内层事务抛出异常e,在内层事务结束时,spring会把事务标记为“rollback-only”。这时如果外层事务捕捉了异常e,那么外层事务方法还会继续执行代码,直到外层事务也结束时,spring发现事务已经被标记为“rollback-only”,但方法却正常执行完毕了,这时spring就会抛出“org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only”。

代码示例如下:

Class ServiceA {@Resource(name = "serviceB")private ServiceB b;@Transactionalpublic void a() {try {b.b()} catch (Exception ignore) {}}
}Class ServiceB {@Transactionalpublic void b() {throw new RuntimeException();}
}

当调用a()时,就会报出“rollback-only”异常。

解决方案:

  • 如果希望内层事务抛出异常时中断程序执行,直接在外层事务的catch代码块中抛出e;
  • 如果希望程序正常执行完毕,并且希望外层事务结束时全部提交,需要在内层事务中做异常捕获处理:
    @Transactionalpublic void b() {try {throw new RuntimeException();}catch (Exception e) {  TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();}}
  • 如果希望内层事务回滚,但不影响外层事务提交,需要将内层事务的传播方式指定为Propagation.REQUIRES_NEW(A和B不需要同一个事务,把事务分开)或者NESTED(A和B同一个事务,但是B回滚的时候A不会回滚)。注:PROPAGATION_NESTED基于数据库savepoint实现的嵌套事务,外层事务的提交和回滚能够控制嵌内层事务,而内层事务报错时,可以返回原始savepoint,外层事务可以继续提交。

UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only相关推荐

  1. Spring事务 Transaction rolled back because it has been marked as rollback-only

    前言 使用Spring事务时,出现异常:org.springframework.transaction.UnexpectedRollbackException: Transaction rolled ...

  2. Transaction rolled back because it has been marked as rollback-only

    http://hsyd.iteye.com/blog/586772 错误信息: Transaction rolled back because it has been marked as rollba ...

  3. 【Spring】21、用spring目标对象处理Transaction rolled back because it has been marked as rollback-only...

    在使用spring做事务管理时,很多人都会遇到这样一段异常: org.springframework.transaction.UnexpectedRollbackException: Transact ...

  4. 关于spring事务传播行为引发的Transaction rolled back because it has been marked as rollback-only

    偶尔博客闲逛发现有人讨论这个问题(我自己没有遇到过),翻了几个帖子没有几个讲清楚的,自己测试下吧 测试类: package com.web.service;import com.StudyApplic ...

  5. Spring嵌套事务异常Transaction rolled back because it has been marked as rollback-only

    项目场景: 在循环里面使用try-catch去捕获异常的时候,并且try里面调的方法它也使用了事务注解 @transactional或者用了事务切面AOP去实现方法事务注入 问题描述 我这里的业务需求 ...

  6. Transaction has been rolled back because it has been marked as rollback

    框架采用的是spring管理声明式事务,这几天业务开发时遇到了点麻烦,记录下备忘. 场景:在Service类中使用子事务(saveponit)时,当子事务抛出异常后,此异常处理掉不继续往外抛,spri ...

  7. Transaction rolled back because it has been marked as rollback-only分析解决方法

    Transaction rolled back because it has been marked as rollback-only分析解决方法 参考文章: (1)Transaction rolle ...

  8. “Transaction rolled back because it has been marked as rollback-only”

    spring的声明事务提供了强大功能,让我们把业务关注和非业务关注的东西又分离开了.好东西的使用,总是需要有代价的.使用声明事务的时候,一 个不小心经常会碰到"Transaction rol ...

  9. Transaction rolled back because it has been marked as rollback-only 原因 和解决方案

    Transaction rolled back because it has been marked as rollback-only 原因 和解决方案 参考文章: (1)Transaction ro ...

最新文章

  1. HTTP协议的挑战者:RSocket
  2. Deep Learning论文笔记之(三)单层非监督学习网络分析
  3. 【论文解读】SIGIR 2020 | 超越用户embedding矩阵:用哈希对大型用户建模
  4. 农行基于TFS工具的敏捷转型实践
  5. LeetCode 27.移除元素 思考分析
  6. 基于java+swing+mysql+JFeeChart的企业人力资源管理系统(2)续
  7. 产品报价单模板_外贸干货 | 外贸人的好东西,报价单这样做才专业!
  8. linux下ip层的一些概念
  9. C 标准库 - string.h之strstr使用
  10. 鼠标移到图片上,图片放大
  11. 数学趣题——猴子吃桃问题
  12. Vue 将字符串保存成 TXT 文件保存到电脑
  13. 省级面板数据(2000-2019)三:人口比、抚养比、就业、失业、离婚、教育(stata版)
  14. envi分类后修改类名称、显示颜色
  15. python金融分析小知识(25)——如何计算股票每日的收益率并进一步计算净值
  16. web项目对接钉钉扫码登录
  17. 判断一个很大的数是否是11的倍数(2种做法)
  18. CodeForces 950C Zebras
  19. 连接数据库出现错误代码为18456
  20. 索尼展示基于MicroLED技术的16K显示屏:约780吋

热门文章

  1. 【matlab图像处理】灰度/点变换实践(1)
  2. EasyYapi接入简单实战
  3. 十五、市场活动:excel导入
  4. 基于图灵机器人的微信自动回复(个人娱乐)
  5. IIS服务器无法播放MP4/FLV/3GP等媒体格式
  6. afn原理 ios_iOS--AFN实现原理
  7. CentOs7 开关防火墙命令
  8. Adobe Photoshop CC for Mac 2019 中文免费版软件在线安装教程
  9. 学习周报之第一周(数据分析)
  10. 给一个数组,和分组数k,代码实现随机分组,尽可能平均分到每个组