项目场景:

在循环里面使用try-catch去捕获异常的时候,并且try里面调的方法它也使用了事务注解 @transactional或者用了事务切面AOP去实现方法事务注入


问题描述

我这里的业务需求是A方法里面调了B方法,并且A和B都有事务,当B出现异常的时候我想获取B的具体报错信息,但是catch这个B方法的时候发生了嵌套事务异常,A方法继续往上抛出导致Transaction rolled back because it has been marked as rollback-only(事务回滚,因为它已被标记为仅回滚)


示例代码如下:

    @transactionalpublic void A(){try{B();}catch(Exception e){e.printStackTrace();}}@transactionalpublic static void B(){System.out.println("测试");}

原因分析:

@Transactional的默认事务传播机制是REQUIRED ,并且B方法抛出异常的时候会标记rollback-only为true,然后A准备提交事务的时候发现rollback-only为true也会进行回滚并且把B抛出的异常信息给吞了。也就是我想要B的异常信息没给,只给了一个rollback-only信息给前端。


事务传播级别 说明
PROPAGATION_REQUIRED 如果当前没有事务,就创建一个事务,如果已经存在事务,就加入到这个事务。当前传播机制也是spring默认传播机制
PROPAGATION_REQUIRES_NEW 新建事务,如果当前存在事务,就抛出异常。
PROPAGATION_SUPPORTS 支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_NOT_SUPPORTED 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_MANDATORY 使用当前的事务,如果当前没有事务,就抛出异常
PROPAGATION_NEVER 以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED 如果当前存在事务,则在嵌套的事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作

解决方案:

1、删除try-catch(不推荐)

这个没什么好说的,就是不进行try-catch,但是很多业务就是需要自己捕获异常,不让用户看到这个异常信息,继续维持服务器的运行。

2、修改事务传播级别

网上最为流传的解决方法就是根据业务设置不同的事务传播级别,将B方法的注解改为REQUIRES_NEW(A和B不需要同一个事务,把事务分开)或者NESTED(A和B同一个事务,但是B回滚的时候A不会回滚),即:

    @Transactional(propagation = Propagation.REQUIRES_NEW)public void B(){System.out.println("测试");}

REQUIRED

  • 假设在A⽅法存在⼀个当前事务,B⽅法的事务传播机制为REQUIRED,则B⽅法会合并到A⽅法的事务⾥执⾏。
  • A、B任意⼀个⽅法异常(默认是RuntimeException和Error)都会导致A、B的操作被回滚。
  • Spring事务管理器不会吞异常。
    B异常后会抛给A,A如果没有catch这个异常,会继续向上抛。如果A catch住了,Spring事务管理器会替A向上抛⼀个
    UnexpectedRollbackException。总之,⼀旦A、B回滚,A的调⽤⽅⼀定能收到⼀个异常感知到回滚。(问题所在)

REQUIRES_NEW

  • 如果B发⽣异常,B事务⼀定回滚,B的异常随后会抛给A,如果A catch住了这个异常,A不会回滚,否则A也会回滚。
  • 如果A发⽣异常,则只会回滚A,不会回滚B。

NESTED

  • 如果B异常,B⼀定回滚,B的异常随后会抛给A,如果A catch住了这个异常,A不会回滚,否则A也会回滚。这种情况和REQUIRES_NEW⼀样。
  • 如果A发⽣异常,则A、B都会回滚。

根据业务需求,后面两个传播级别是不符合我的需求的,因为会导致A或B的事务不回滚,第一个传播级别REQUIRED才符合但有问题,即第一个方法对我无效,大家可以先试试。

3、手动回滚(推荐)

这个是我在逛了无数的论坛和提问才发现的解决方案,在catch语句中增加:TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();语句,手动回滚,这样上层就无需去处理异常
示例代码如下:

    @Transactionalpublic void A(){try{B();}catch(Exception e){TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();e.printStackTrace();}}@Transactionalpublic void B(){System.out.println("测试");}

参考文章:
事务传播级别(7种)
Spring事务嵌套引发的血案—Transaction rolled back because it has been marked as rollback-only

Spring嵌套事务异常Transaction rolled back because it has been marked as rollback-only相关推荐

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

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

  2. 关于Spring嵌套事务异常问题

    关于Spring嵌套事务异常问题 异常截图 异常信息: Transaction silently rolled back because it has been marked as rollback- ...

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

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

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

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

  5. UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only

    转载自:https://dongguabai.blog.csdn.net/article/details/114686998 PROPAGATION_REQUIRES_NEW:原有事务A新起事务B,事 ...

  6. 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 ...

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

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

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

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

  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 rolle ...

最新文章

  1. MPB:南农金巍等-​​​瘤胃甲烷菌的分离培养与保存
  2. c++98不支持set初始化列表
  3. Android PC投屏简单尝试—最终章1
  4. Elasticsearch嵌套查询
  5. HTML+CSS+JS实现美女照片3D立方体旋转特效
  6. Any-Proxy在线反向代理源码
  7. c语言程序设计课用电脑吗,C语言程序设计之简单计算器
  8. 《葵花宝典:WPF自学手册》三大网点书评集萃
  9. php怎么写脚本,PHP脚本来写Daemon程序_php
  10. RAID结构介绍以及RAID1、RAID0等各种模式的区别
  11. Unicode编码表
  12. pgadmin3连接mysql_postgresql – pgAdmin III:拒绝访问数据库
  13. 有了这套前端数据可视化框架,人人都能快速上手(赠100套前端可视化大屏模板)
  14. 【Python实用工具】查询本机IP地址
  15. 【优化系列】汇编优化技术(六):ARM架构64位(AARCH64)汇编优化及demo
  16. npm 实战精讲-曾亮-专题视频课程
  17. 20210514面试题自我分类及总结(一)
  18. 微观经济学论文选题怎么选?
  19. pandas 第十二期组队-pandas基础
  20. 数据代码分享|Python用NLP自然语言处理LSTM神经网络Twitter推特灾难文本数据、词云可视化与SVM,KNN,多层感知器,朴素贝叶斯,随机森林,GBDT对比

热门文章

  1. div的水平排列、垂直排列
  2. 哈登独得40分保罗复出 火箭主场103:98复仇魔术
  3. 计算机常用快捷键(世上最全)
  4. scala中sorted,sortby,sortwith的用法(转)
  5. 画油画,笔触的重要性原来体现在这里~
  6. 打字游戏c语言easyx,打字小游戏(天降字母)Visual Studio+EasyX
  7. appium连接ios手机
  8. 接口文档编写步骤与格式
  9. Manacher思想 SCOI2013 密码
  10. 盛迈坤电商:运营店铺需要怎么做