Spring事务报错: org.springframework.transaction.UnexpectedRollbackException
创始人
2025-05-29 09:28:51
0

异常信息:支持当前事务,如果不存在则抛出异常。事务被回滚,因为它被标记为仅回滚

org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-onlyat org.springframework.transaction.support.AbstractPlatformTransactionManager.processRollback(AbstractPlatformTransactionManager.java:873)at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:710)at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:533)at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:304)at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)

Spring事务传播机制:可以查看如下枚举
总结如下:

  • PROPAGATION_REQUIRED:如果当前没有事务,就新建一个事务,如果已经存在一个事务,就加入到这个事务中。默认策略
  • PROPAGATION_SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。
  • PROPAGATION_MANDATORY:使用当前的事务,如果当前没有事务,就抛出异常。
  • PROPAGATION_REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。
  • PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
  • PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
  • PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。
    nested 的子异常抛出 如果被catch 外部插入成功 nested 的子异常抛出 如果不被catch 外部插入失败
    nested外面异常抛出 nest内部插入成功 nest也会跟着回滚
/** Copyright 2002-2018 the original author or authors.** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**      https://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/package org.springframework.transaction.annotation;import org.springframework.transaction.TransactionDefinition;/*** Enumeration that represents transaction propagation behaviors for use* with the {@link Transactional} annotation, corresponding to the* {@link TransactionDefinition} interface.** @author Colin Sampaleanu* @author Juergen Hoeller* @since 1.2*/
public enum Propagation {/*** Support a current transaction, create a new one if none exists.* Analogous to EJB transaction attribute of the same name.* 

This is the default setting of a transaction annotation.*/REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED),/*** Support a current transaction, execute non-transactionally if none exists.* 支持当前事务,如果不存在则以非事务方式执行。* Analogous to EJB transaction attribute of the same name.* Note: For transaction managers with transaction synchronization,* PROPAGATION_SUPPORTS is slightly different from no transaction at all,* as it defines a transaction scope that synchronization will apply for.* As a consequence, the same resources (JDBC Connection, Hibernate Session, etc)* will be shared for the entire specified scope. Note that this depends on* the actual synchronization configuration of the transaction manager.* 注意:对于具有事务同步的事务管理器,PROPAGATION_SUPPORTS与完全没有事务略有不同因为它定义了同步将应用的事务范围因此,相同的资源(JDBC连接,Hibernate Sess将为整个指定范围共享。注意,这取决于事务管理器的实际同步配置。* @see org.springframework.transaction.support.AbstractPlatformTransactionManager#setTransactionSynchronization*/SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS),/*** Support a current transaction, throw an exception if none exists.* 支持当前事务,如果不存在则抛出异常。* Analogous to EJB transaction attribute of the same name.*/MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY),/*** Create a new transaction, and suspend the current transaction if one exists.* 创建一个新事务,如果存在当前事务,则挂起当前事务。* Analogous to the EJB transaction attribute of the same name.*

NOTE: Actual transaction suspension will not work out-of-the-box* on all transaction managers. This in particular applies to* {@link org.springframework.transaction.jta.JtaTransactionManager},* which requires the {@code javax.transaction.TransactionManager} to be* made available to it (which is server-specific in standard Java EE).* @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager*/REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW),/*** Execute non-transactionally, suspend the current transaction if one exists.* 以非事务方式执行,如果存在当前事务,则暂停当前事务。* Analogous to EJB transaction attribute of the same name.*

NOTE: Actual transaction suspension will not work out-of-the-box* on all transaction managers. This in particular applies to* {@link org.springframework.transaction.jta.JtaTransactionManager},* which requires the {@code javax.transaction.TransactionManager} to be* made available to it (which is server-specific in standard Java EE).* @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager*/NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED),/*** Execute non-transactionally, throw an exception if a transaction exists.* 以非事务方式执行,如果存在事务则抛出异常。* Analogous to EJB transaction attribute of the same name.*/NEVER(TransactionDefinition.PROPAGATION_NEVER),/*** Execute within a nested transaction if a current transaction exists,* 如果当前事务存在,则在嵌套事务中执行,* behave like PROPAGATION_REQUIRED else. There is no analogous feature in EJB.* 行为类似于PROPAGATION_REQUIRED else。EJB中没有类似的特性。*

Note: Actual creation of a nested transaction will only work on specific* transaction managers. Out of the box, this only applies to the JDBC* DataSourceTransactionManager when working on a JDBC 3.0 driver.* Some JTA providers might support nested transactions as well.* @see org.springframework.jdbc.datasource.DataSourceTransactionManager*/NESTED(TransactionDefinition.PROPAGATION_NESTED);private final int value;Propagation(int value) {this.value = value;}public int value() {return this.value;}}

spring事务默认的传播行为:
@Transactional 等于 @Transactional(propagation=Propagation.REQUIRED)

发生异常的场景描述:
在使用Spring事务时,在一个事务A中又开了一个事务B(即存在嵌套事务),当事务B发生异常时,将异常catch后事务B会进行回滚操作,若此时异常被直接吃掉(即事务A无法得知发生过异常),则事务A会抛出如上异常。

serviceA有事务 @TransactionalserviceB有事务 @Transactional有@TransactionalServiceA -> {ServiceAtry {@Transactional()ServiceB{异常 BusinessException事务回滚}} catch (Exception e) {}} 

原因:
因为ServiceB的传播属性设置为PROPAGATION_REQUIRED,PROPAGATION_REQUIRED的意思是,当前有事务,则使用当前事务,当前无事务则创建事务。由于ServiceA的传播属性也为PROPAGATION_REQUIRED,所以ServiceA会创建一个事务,然后ServiceB与ServiceA使用同一个事务,ServiceB出现异常后,将当前事务标志位回滚,由于在ServiceA中做了trycatch处理,程序没有终止而是继续往下走,当事务commit时,check状态,发现,需要事务回滚,所以才会出现不可预知的事务异常:因为事务被标志位回滚,所以事务回滚。
也就是说:ServiceA与ServiceB共用一个事务,ServiceB将事务标志为回滚,ServiceA中commit这个事务,然后,出现事务已经被标志回滚(ServiceB标志的)的异常信息。

解决方案
情况1:ServiceA与ServiceB在逻辑上不应该属于同一个事务,那么将ServiceB的事务传播属性修改为PROPAGATION_REQUIRES_NEW,这样,执行ServiceB时,会创建一个新的事务,不影响ServiceA中的事务。

情况2:业务A与业务B在业务逻辑上就应该属于同一个事务,那么将ServiceA中的try catch去掉

情况3:业务A与业务B在业务逻辑上就应该属于同一个事务,但是ServiceB的失败与否不能影响ServiceA的事务提交,那么仍然在ServiceA中try catch ServiceB,并将ServiceB设置为PROPAGATION_NESTED,它的意思是,ServiceB是一个子事务,有一个savepoint,失败时会回滚到savepoint,不影响ServiceA,如果成功则A、B一起提交,A与B都是一个事务,只是B是一个子事务。
情况4:业务A 有无事务无影响 去掉业务A的@Transactional

相关内容

热门资讯

车载以太网 - 测试用例设计 ... 关于诊断消息相关的介绍前面的文章已经有了比较清晰的介绍,测试用例设计实际就是对于规范的解读,然后通过...
安顺推动文化生态保护与旅游发展... 本文转自:人民网-贵州频道人民网贵阳5月30日电 (陈洁泉)5月30日,2025年“避暑度假到贵州”...
JavaScript引入方式和... 【案例1-2】 JavaScript引入方式 一、案例描述 考核知识点JavaScript的几种引入...
光亚展-文商旅视觉展,集结超1... 据文化和旅游部最新数据,2025年“五一”假期全国国内出游人次达3.14亿,同比增长6.4%;国内游...
新晋打卡地!富官庄镇箕山未来田... 箕山未来田园首批项目今日启用 “六一”儿童节来临之际,富官庄镇箕山未来田园旅游度假区首批项目顺利启用...
阳朔民宿酒店推荐·2025年度... 在阳朔这片充满喀斯特地貌奇观的土地上,每一处民宿酒店都像是镶嵌在山水之间的宝石,以其独特的魅力吸引着...
好消息~川沙南侧将新建一座地标... 上海文旅项目建设传来喜讯! 迪士尼的“邻居”有重磅消息! 从5月26日举办的浦东新区重点片区推介会上...
Spring框架及源码学习--... Spring手写IOC和AOP一主要内容第⼀部分 Spring 概述第1节 Spring 简介第2节...
找一找马里奥-第14届蓝桥杯S...  [导读]:超平老师的《Scratch蓝桥杯真题解析100讲》已经全部完成࿰...
藕遇骨香:一锅慢炖出的荆楚岁月... 在中华美食的星河中,排骨藕汤宛如一盏温润的明灯,以醇厚浓郁的汤头、粉糯清甜的莲藕和鲜嫩多汁的排骨,在...
白酒如何构筑品牌美学?国窖15... 文 | 李霞 过去几年,大众对非遗的关注与讨论呈现爆发式增长趋势。 《2025抖音非遗数据报告》显示...
啤酒之光!燕京啤酒获评2025... 5月25日,2025(第九届)中国品牌博鳌峰会在海南隆重召开,本次峰会以“献礼510中国品牌日 共筑...
辽宁特色椒盐皮皮虾,简单几步就... 在辽宁的海鲜江湖里,椒盐皮皮虾可是响当当的“明星选手”。它外壳酥脆、虾肉鲜嫩,带着浓郁的椒盐香气,让...
新疆烤包子逆袭!内馅加芝士,酥... 在新疆的街头巷尾,总能看到烤包子的身影。那一个个整齐地贴在馕坑内壁的烤包子,金黄酥脆的外皮,散发着诱...
香菜自由汉堡:加多少都不心疼,... 在美食的世界里,总有一些食材如同个性鲜明的主角,一出场就能牢牢抓住特定人群的味蕾,香菜便是其中之一。...
大山劳模开出的“早班车” 邓兰舟驾驶的公交车被挂牌“民主早班车”。 帮村民义务带货17年。本组图片由受访者提供 “艾常全:磷...
五毒月九毒日即将来临!这些养生... 内容来源:中国中医药报(有删改) 作者:王碧辉 山东省济宁市中医院 传统 阴历五月俗称毒月,其中有九...