Spring 内部事务调用导致事务实效解决方法

news/2024/12/27 16:03:43/文章来源:https://www.cnblogs.com/wgy1/p/18635985
Spring 事务,当方法内部调用的时候, 事务会失效。
/** 
* 在事务A方法中,直接调用事务B方法,B方法拥有事务的能力是因为 spring aop 生成了代理对象,但是方法直接调用了this对象的方法,所以B方法不会生成事务。
* 这里的@Transactional 将会失效
*/
@Transactional
public void edit(User user) {editMsgByUser(user);// .......
}@Transactional
public void editMsgByUser(User user) {// 这里的事务如果会滚,当前这个方法的事务就会失效。
}

 

如果看上面这个例子,即使B事务失效,A事务也会出发会滚。 也能做到会滚的效果。
但是实际应用中,遇到一种场景。
/** 
* 这是批量新增的接口, 接口要求, 批量进增时,新增成功返回成功数据, 失败的返回异常数据。 
*/
public List<OutboundApplyNotesDTO> insertOutboundApplyNoteList(List<CreateOutboundApplyNoteDTO> dto) {List<OutboundApplyNotesDTO> dataList = Lists.newArrayList();for(CreateOutboundApplyNoteDTO createOutboundApplyNoteDTO : dto) { try {List<OutboundApplyNoteDetailIdDTO> applyNoteDetailids = insertOutboundApplyNote(createOutboundApplyNoteDTO);OutboundApplyNotesDTO applyNotesDTO = OutboundApplyNotesDTO.builder().insertCode(OutboundResponseEnum.SUCCESS.getCode()).insertMsg(OutboundResponseEnum.SUCCESS.getMessage()).build();dataList.add(applyNotesDTO);} catch (Exception e) {log.error("新增出库申请单异常:", e);OutboundApplyNotesDTO applyNotesDTO = OutboundApplyNotesDTO.builder().insertCode(OutboundResponseEnum.ADD_ERROR.getCode()).insertMsg(e.getMessage()).build();dataList.add(applyNotesDTO);}}return dataList;
}/**
* 这里进行单个单据的插入, 如果插入中有异常抛出,数据需要会滚。 
*/
@Transactional(rollbackFor = Exception.class)
public List<OutboundApplyNoteDetailIdDTO> insertOutboundApplyNote(CreateOutboundApplyNoteDTO dto) {// throw new BusinessException(OutboundResponseEnum.ORDER_EXIST, valNote.getOutboundApplyNoteNo());return new List();
}

 

在上面这个接口中, 接口A 不允许抛出异常,B接口如果有异常,需要回滚。 但是此时B方法中事务没有生效,就会造成尴尬。
当Spring容器启动时候, 发现有 @EnableTransactionManagement 注解,会拦截所有bean的创建,扫描bean上是否有 @Transaction 注解,如果有这个注解,spring 会通过 aop方法给这个bean生成代理对象(代理对象存在本类对象),代理对象中会增加一个拦截器,拦截器会拦截bean中public方法的执行,在方法执行前启动事务,方法执行完毕之后提交或者回滚事务。
 
事务生效:必须通过代理对象来调用方法。代理对象最终都是要调用原始对象的,而原始对象去调用方法时,是不会再出发代理了。
所以同一个类中, A调用 B, B方法上的事务不会单独生效。
此时又遇到了,上面这种业务场景。 就需要考虑,把这两个方法,放到不同的类中去。
/** 
* 对外提供的Controller 方法,
* 里面有两个方法, 一个单个新增, 一个批量新增。 
*/
@RestController
@Api(value = "出库申请单相关")
@RequiredArgsConstructor
public class OutboundApplyController implements IWmsController, OutboundApplyNoteApiService {// 这里分开两个service方法 private final OutboundApplyNoteService outboundApplyNoteService;private final OutboundApplyNoteDetailService outboundApplyNoteDetailService;@Overridepublic Result<List<OutboundApplyNoteDetailIdDTO>> insertOutboundApplyNote(CreateOutboundApplyNoteDTO dto) {List<OutboundApplyNoteDetailIdDTO> data = outboundApplyNoteService.insertOutboundApplyNote(dto);return ok(data);}@Overridepublic Result<List<OutboundApplyNotesDTO>> insertOutboundApplyNoteList(List<CreateOutboundApplyNoteDTO> dto) {List<OutboundApplyNotesDTO> data = outboundApplyNoteDetailService.insertOutboundApplyNoteList(dto);return ok(data);}}/**
* A 类, A方法 
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class OutboundApplyNoteDetailServiceImpl extends WmsService implements OutboundApplyNoteDetailService {private final OutboundApplyNoteService outboundApplyNoteService;/** * 这是批量新增的接口, 接口要求, 批量进增时,新增成功返回成功数据, 失败的返回异常数据。 */public List<OutboundApplyNotesDTO> insertOutboundApplyNoteList(List<CreateOutboundApplyNoteDTO> dto) {List<OutboundApplyNotesDTO> dataList = Lists.newArrayList();for(CreateOutboundApplyNoteDTO createOutboundApplyNoteDTO : dto) { try {List<OutboundApplyNoteDetailIdDTO> applyNoteDetailids = outboundApplyNoteService.insertOutboundApplyNote(createOutboundApplyNoteDTO);OutboundApplyNotesDTO applyNotesDTO = OutboundApplyNotesDTO.builder().insertCode(OutboundResponseEnum.SUCCESS.getCode()).insertMsg(OutboundResponseEnum.SUCCESS.getMessage()).build();dataList.add(applyNotesDTO);} catch (Exception e) {log.error("新增出库申请单异常:", e);OutboundApplyNotesDTO applyNotesDTO = OutboundApplyNotesDTO.builder().insertCode(OutboundResponseEnum.ADD_ERROR.getCode()).insertMsg(e.getMessage()).build();dataList.add(applyNotesDTO);}}return dataList;}
}/**
* B 类 B方法 
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class OutboundApplyNoteServiceImpl extends WmsService implements OutboundApplyNoteService {/*** 这里进行单个单据的插入, 如果插入中有异常抛出,数据需要会滚。 */@Transactional(rollbackFor = Exception.class)public List<OutboundApplyNoteDetailIdDTO> insertOutboundApplyNote(CreateOutboundApplyNoteDTO dto) {// throw new BusinessException(OutboundResponseEnum.ORDER_EXIST, valNote.getOutboundApplyNoteNo());return new List();}
}

 

这样就可以解决遇到的B事务未生效的情况。
  
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/859888.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【工作相关】gki boot.img下载

地址 https://source.android.com/docs/core/architecture/kernel/gki-android13-5_15-release-builds?hl=zh-cn Android13-5.15 发布版本查看Linux version信息: 相关解包命令参考这里【传送门】 解包过程:~/cts/gki$ ../bin/unpack_bootimg --boot_img boot-5.15.img --ou…

鸿蒙NEXT开发实战教程—小红书app

幽蓝君最近发现小红书是个好东西,一定要多逛今天就浅浅模仿一下小红书app,主要是底部tab栏和主页部分。首先看一下tabbar,由于中间有一个红色按钮的存在,所以这里我使用自定义导航栏来实现,自定义的实现逻辑是在本来app的上层叠加一层自定义tabbar,使用监听index的变化来…

Python数据结构之双向循环链表

1、循环双向链表特点通过当前结点直接获取上一结点 通过头结点的上一结点直接可以去找到尾结点 可以进行反向循环链表,即反转链表2、头结点 链表头: 在数据结构中,链表是一种常见的存储结构。链表的每个节点包含数据和指向下一个节点的指针。链表头是链表的第一个节点,它在…

CDS标准视图:功能位置 I_FunctionalLocation

视图名称:I_FunctionalLocation 视图类型:基础 视图代码:点击查看代码 @EndUserText.label: Functional Location @Analytics: { dataCategory: #DIMENSION } @VDM.viewType: #BASIC @AbapCatalog: { sqlViewName: IFUNCTLLOCATION, compiler.compareFilter, preserveKey } …

DNS 原理入门

DNS 原理入门 导读 DNS 是互联网核心协议之一。不管是上网浏览,还是编程开发,都需要了解一点它的知识。本文详细介绍DNS的原理,以及如何运用工具软件观察它的运作。我的目标是,读完此文后,你就能完全理解DNS。一、DNS 是什么? DNS (Domain Name System 的缩写)的作用非…

Pycharm 2024.3 安装详细教程与激活方法(附常见问题解决)

Pycharm概述 Pycharm是JetBrains公司推出的一款功能强大的Python集成开发环境(IDE),凭借其丰富的功能和工具集,极大地提升了开发者的编程效率和工作体验。温馨提示: 本文中的方法仅供学习交流使用,如果条件允许,请支持正版软件。删除旧版本 Pycharm 如果您的电脑中已经安…

算法网关视频分析网关小知识:如何对视频分析系统实施冗余设计以提高稳定性?

在城市交通管理中,视频分析系统扮演着至关重要的角色,它不仅需要实时监控和分析交通流量,还需要在各种复杂环境下保持稳定运行。为了确保视频分析系统在面对设备故障、网络中断、电源波动等不可预见情况时仍能保持高可用性,实施冗余设计成为了提高系统稳定性的关键策略。以…

敏捷销售的基础:协同工具如何助力车企升级

今年来,国家在汽车产业领域频频出台利好政策,从新能源汽车补贴延续到以旧换新购车补贴,这一系列措施为汽车企业创造了全新的市场机遇。然而,面对复杂的销售网络、多样的营销活动和庞大的数据管理需求,车企如何迅速响应政策、提升协作效率,成为当前的核心挑战。 政策推动下…

在北大的第一学期结课小记——2024.12.27

本来是想昨天下午写的,因第一学期之课程在26日上午第四节课便已然完结,但却因个人的懒惰拖到了今日,我实在是罪无可恕,愿不要在接下来的期末复习上延续此般习气在开学初,本学期的选课方案可谓充满了妥协与权衡:为防掉课线代放弃了xsq,计概放弃了yhf,物院思修强制选课撞…

工作坊报名|使用 TEN Framework 与 Azure,探索你的多模态交互新场景

活动背景 GPT-4o Realtime API 发布,语音 AI 正在进入一场新的爆发。AI 的实时语音和视觉互动能力将为我们带来更多全新创意和应用场景。实时音频交互:允许应用程序实时接收并响应语音和文本输入。 自然语音生成:减少 AI 语音的机械感,使对话更加人性化。 多语言能力:促进…

【2】UDS诊断的请求和响应

1. 常见的UDS服务 UDS共包含6大类,26个服务。其中常用的有:诊断和通信管理中的10(诊断会话控制)、11(ECU 复位)、27(安全访问)、3E(待机握手),数据传输功能中的22(通过ID读数据)、2E(通过ID写数据),存储数据传输功能的14(清除诊断信息)、19(读取故障码信息)…

学习破解一个Android程序

首先编写一个android测试程序 功能:校验用户名和注册码,成功则弹出注册成功提示 以下仅给出关键部分的代码 res/layout/activity_main.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.androi…