SpringDataJPA使用deleteAllInBatch方法逻辑删除失效
概述
在使用Spring Boot JPA时,执行批量删除操作时,遇到逻辑删除失效的问题。具体而言,当使用deleteAllInBatch方法时,数据会被物理删除,而不是进行逻辑删除;但是当使用deleteAll时,逻辑删除操作可以正常生效。经过调查,发现deleteAllInBatch方法和deleteAll方法的行为有所不同,导致逻辑删除失败。
症状
- 使用
deleteAllInBatch方法时,数据直接从数据库中物理删除。 - 使用
deleteAll方法时,逻辑删除生效,数据并未被物理删除,而是更新了delLogic字段。
使用的实体类代码
@Entity
public class TemplateField {@Idprivate Long id;private Integer delLogic; // 用于标记是否被逻辑删除@PreRemovepublic void templateField() {this.setDelLogic(1); // 设置逻辑删除标记}@SQLDelete(sql = "UPDATE t_template_field SET del_logic = 1 WHERE id = ?")@Where(clause = "del_logic = 0") // 过滤删除标记为0的数据public void setDelLogic(Integer delLogic) {this.delLogic = delLogic;}
}
问题原因
问题的根本原因是deleteAllInBatch和deleteAll在执行删除操作时的实现方式不同,导致生命周期回调方法(如@PreRemove)未被触发。
deleteAllInBatch和deleteAll的区别
-
deleteAll():该方法会逐个加载实体,并在JPA上下文中处理每个实体的删除操作。每次删除实体时,都会触发实体的生命周期回调方法(如@PreRemove、@PostRemove等)。因此,当使用deleteAll()方法时,你在实体类上定义的逻辑删除(例如通过@PreRemove标记设置删除标记)可以生效。 -
deleteAllInBatch():该方法是一个批量删除操作,通常是直接生成SQL语句一次性删除数据,不会逐个加载实体,因此也不会触发实体的生命周期回调方法。批量操作的优势在于效率较高,但缺点是无法触发与实体相关的生命周期事件,如@PreRemove和@PostRemove。
deleteAllInBatch导致物理删除的原因
deleteAllInBatch()方法并不会按@PreRemove中的逻辑设置delLogic字段,而是直接执行数据库的物理删除操作。这就是为什么在使用deleteAllInBatch()时,数据会被直接从数据库中删除,而不是进行逻辑删除的原因。
问题解决方案
要解决这个问题,通常有以下几种方式:
方案 1:使用deleteAll()替代deleteAllInBatch()
如果逻辑删除的需求比性能更为重要,并且不介意性能稍微下降,可以直接使用deleteAll()方法。这会逐个处理实体,并触发相应的生命周期回调方法,从而确保逻辑删除(即更新delLogic字段)生效。
方案 2:自定义批量更新方法
如果依然希望使用批量删除操作(如deleteAllInBatch()),可以自定义一个批量更新的方法,通过直接执行SQL更新操作来实现逻辑删除。这种方式可以保证批量操作时的效率,同时避免物理删除数据。
例如,使用@Modifying和@Query注解,执行批量更新操作:
@Modifying
@Query("UPDATE TemplateField tf SET tf.delLogic = 1 WHERE tf.id IN :ids")
int batchLogicalDelete(@Param("ids") List<Long> ids);
该方法会直接更新符合条件的记录,将delLogic字段设置为1,达到逻辑删除的效果。
方案 3:手动更新实体后再执行批量删除
可以先通过查询获取所有需要“删除”的实体,将它们的delLogic字段设置为逻辑删除标志,然后再调用deleteAllInBatch()进行删除操作。
代码示例:
List<TemplateField> fields = templateFieldRepository.findAllById(ids);
fields.forEach(field -> field.setDelLogic(1)); // 更新逻辑删除标志
templateFieldRepository.saveAll(fields); // 保存更新
templateFieldRepository.deleteAllInBatch(fields); // 执行批量删除
这种方式在批量删除前,先手动更新实体,确保逻辑删除字段被正确设置。
问题示例代码
使用deleteAll()进行逻辑删除
List<TemplateField> fields = templateFieldRepository.findAllById(ids);
fields.forEach(field -> field.setDelLogic(1)); // 更新逻辑删除标志
templateFieldRepository.saveAll(fields); // 保存更新
templateFieldRepository.deleteAll(fields); // 执行逐个删除(触发生命周期方法)
自定义批量更新方法进行逻辑删除
@Modifying
@Query("UPDATE TemplateField tf SET tf.delLogic = 1 WHERE tf.id IN :ids")
int batchLogicalDelete(@Param("ids") List<Long> ids);// 调用自定义批量逻辑删除方法
templateFieldRepository.batchLogicalDelete(ids);
手动更新实体后再执行批量删除
List<TemplateField> fields = templateFieldRepository.findAllById(ids);
fields.forEach(field -> field.setDelLogic(1)); // 更新逻辑删除标志
templateFieldRepository.saveAll(fields); // 保存更新
templateFieldRepository.deleteAllInBatch(fields); // 执行批量删除
总结
deleteAllInBatch()方法直接执行SQL批量删除,不会触发实体的生命周期回调方法(如@PreRemove),导致逻辑删除无效。- 如果需要触发回调方法,可以使用
deleteAll(),但会影响性能。 - 也可以自定义批量逻辑删除方法,通过直接更新
delLogic字段来避免物理删除。
相关文章:
SpringDataJPA使用deleteAllInBatch方法逻辑删除失效
概述 在使用Spring Boot JPA时,执行批量删除操作时,遇到逻辑删除失效的问题。具体而言,当使用deleteAllInBatch方法时,数据会被物理删除,而不是进行逻辑删除;但是当使用deleteAll时,逻辑删除操…...
DOM Node
DOM Node 引言 在Web开发中,DOM(Document Object Model)节点是构建网页和交互式应用程序的核心。DOM节点是文档的构建块,可以用来表示HTML和XML文档中的任何部分。本文将详细介绍DOM节点的基本概念、类型、操作方法以及在实际开发中的应用。 什么是DOM节点? DOM节点是…...
基于STM32的智能家居能源管理系统
1. 引言 传统家庭能源管理存在能耗监控粗放、设备联动不足等问题,难以适应绿色低碳发展需求。本文设计了一款基于STM32的智能家居能源管理系统,通过多源能耗监测、负荷预测与优化调度技术,实现家庭能源的精细化管理与智能优化,提…...
智慧园区后勤单位消防安全管理:安全运营和安全巡检
//智慧园区消防管理困境大曝光 智慧园区,听起来高大上,但消防管理却让人头疼不已。各消防子系统各自为政,像一座座孤岛,信息不共享、不协同。 消防设施管理分散,不同区域、企业的设备标准不一样,维护情况…...
HTML 日常开发常用标签
文章目录 HTML 日常开发常用标签1、基本结构标签2、内容标签3、多媒体标签4、表单标签5、列表和定义标签6、表格标签7、链接和图像8、元数据9、语义化标签(HTML5新增)10、框架和内联11、交互12、过时或不推荐使用的标签 HTML 日常开发常用标签 1、基本结…...
Spring事务失效六大场景
引言 Spring事务一般我们采用注解实现,但是我们构造事务实现的时候常常没察觉失效的情况,本篇文章总结事务失效的六大情况,帮助我们深刻理解事务失效的边界概念 1. 方法自调用 这个主要是针对声明式事务的,经过前面的介绍&…...
【缓冲区】数据库备份的衍生问题,缓冲区在哪里?JVMor操作系统?(二)
【缓冲区】数据库备份的衍生问题,缓冲区在哪里?JVMor操作系统?(二 完结) 缓冲区既属于操作系统,也属于 JVM,具体取决于你讨论的是哪个层面的缓冲区。下面我会详细解释这两者的区别和联系。 1. …...
如何免费使用稳定的deepseek
0、背景: 在AI辅助工作中,除了使用cursor做编程外,使用deepseek R1进行问题分析、数据分析、代码分析效果非常好。现在我经常会去拿行业信息、遇到的问题等去咨询R1,也给了自己不少启示。但是由于官网稳定性很差,很多…...
钉钉小程序(企业内部应用)开发--钉钉小程序web-view嵌套H5与小程序之间的通信(H5跳转钉钉小程序小程序postMessage)
钉钉小程序代码:嵌套H5 pages/login/index.axml <web-view src"{{urlH5}}" onMessage"test"></web-view> H5向小程序发送信息: H5代码: 通过以下代码我一直报错dd没有被定义 if (navigator.userAgent.to…...
超级免费/牛的图片格式转换工具jpg/jpeg/png
选择多次图片文件,并在所有图片选择完后进行批量转换。这种需求可以通过tkinter来实现,它是Python的标准GUI库,能够提供一个简洁的界面来选择文件和执行操作。您的代码要是网络运行不流畅可以试试它 下面是一个简单的GUI程序&a…...
毛泽东思想“活的灵魂”
关于毛泽东思想“活的灵魂”的构成及其内涵,综合历史文献与权威表述,核心内容整理如下: 一、毛泽东思想活的灵魂的权威定义 根据十一届六中全会《关于建国以来党的若干历史问题的决议》(1981年),毛泽东思想…...
RabbitMQ系列(三)基本概念之Consumer
在 RabbitMQ 中,Consumer(消费者) 是负责从队列(Queue)中获取并处理消息的客户端角色,其核心机制与功能如下: 一、Consumer 的定义与核心作用 消息处理终端 Consumer 通过订阅或拉取队列中的消…...
天梯L2-003 月饼
L2-003 月饼 - 团体程序设计天梯赛-练习集 def slove():n,m map(float,input().split())z list(map(float,input().split()))y list(map(float,input().split()))n int(n)d []for i in range(n):d.append([z[i],y[i]])d.sort(key lambda x:x[1]/x[0],reverse True)cnt…...
使用DeepSeek/ChatGPT等AI工具辅助编写wireshark过滤器
随着deepseek,chatgpt等大模型的能力越来越强大,本文将介绍借助deepseek,chatgpt等大模型工具,通过编写提示词,辅助生成全面的Wireshark显示过滤器的能力。 每一种协议的字段众多,流量分析的需求多种多样,…...
常用的AI文本大语言模型汇总
AI文本【大语言模型】 1、文心一言https://yiyan.baidu.com/ 2、海螺问问https://hailuoai.com/ 3、通义千问https://tongyi.aliyun.com/qianwen/ 4、KimiChat https://kimi.moonshot.cn/ 5、ChatGPThttps://chatgpt.com/ 6、魔塔GPT https://www.modelscope.cn/studios/iic…...
《深度剖析:特征工程—机器学习的隐秘基石》
在机器学习的宏大版图中,特征工程宛如一座隐藏在幕后却又至关重要的基石。它默默发挥着作用,将原始数据雕琢成模型能够有效学习和理解的形态,深刻影响着机器学习模型的性能与表现。 特征工程:机器学习的关键前奏 特征工程是运用…...
解决npm run dev报错
解决:Node.js 版本更新后与 OpenSSL 不兼容导致的npm报错“Error: error:0308010C:digital envelope routines::unsupported” 方法一:更改系统环境变量方法二:更改项目环境变量方法三:更换 Node.js 版本方法四:升级依…...
教你通过腾讯云AI代码助手,免费使用满血版deepseek r1,还可以自定义知识库!
大家好,今天教大家如何通过腾讯云AI代码助手,免费使用全世界最牛逼的deepseek大模型的deepseek r1满血版! 1. 环境准备 提前下载好下面任意的一款编程使用的代码编辑器 Visual Studio CodeJetBrains IDEsVisual Studio微信开发者工具 2. 下载安装 打…...
【C++/数据结构】栈的模拟实现
零.导言 栈是一种数据结构,在后续的学习中可能经常使用,因此我们今天就来学习如何实现栈,以更好地使用它。 一.栈的模拟实现 栈的形式如下: #include<iostream> #include<cassert>using namespace std;typedef int S…...
StarRocks 开发环境搭建踩坑指北之存算分离篇
前段时间碰到一个 StarRocks 物化视图的 bug: https://github.com/StarRocks/starrocks/issues/55301 但是这个问题只能在存算分离的场景下才能复现,为了找到问题原因我便尝试在本地搭建一个可以 Debug 的存算分离版本。 之前也分享过在本地 Debug StarRocks&#x…...
2025最权威的五大AI论文平台推荐榜单
Ai论文网站排名(开题报告、文献综述、降aigc率、降重综合对比) TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 借助人工智能来辅助撰写开题报告,这是需要依照系统性方法去做的。首先呢…...
和AI一起搞事情#:边剥龙虾边做个中医技能来起号戏
1. 核心概念 在 Antigravity 中,技能系统分为两层: Skills (全局库):实际的代码、脚本和指南,存储在系统级目录(如 ~/.gemini/antigravity/skills)。它们是“能力”的本体。 Workflows (项目级):…...
三开关双Boost高增益DC/DC变换器建模与控制仿真研究
三开关双Boost高增益DC/DC变换器建模与控制仿真研究 摘要 在光伏发电、燃料电池及电动汽车高压充电等新能源应用场景中,高增益DC-DC变换器是实现低压源与高压直流母线高效匹配的关键环节。传统的非隔离Boost变换器受限于寄生参数和极限占空比约束,难以满足高升压比的需求,…...
破解心理健康AI难题:20,000条专业心理咨询语料库实战指南
破解心理健康AI难题:20,000条专业心理咨询语料库实战指南 【免费下载链接】efaqa-corpus-zh ❤️Emotional First Aid Dataset, 心理咨询问答、聊天机器人语料库 项目地址: https://gitcode.com/gh_mirrors/ef/efaqa-corpus-zh 当开发者尝试构建心理健康AI助…...
如何用OpCore-Simplify在30分钟内完成黑苹果EFI自动化配置?
如何用OpCore-Simplify在30分钟内完成黑苹果EFI自动化配置? 【免费下载链接】OpCore-Simplify A tool designed to simplify the creation of OpenCore EFI 项目地址: https://gitcode.com/GitHub_Trending/op/OpCore-Simplify 黑苹果(Hackintosh…...
BGE-Large-Zh对比OpenAI:中文语义理解能力评测
BGE-Large-Zh对比OpenAI:中文语义理解能力评测 1. 评测背景与意义 语义理解模型在当今AI应用中扮演着越来越重要的角色,特别是在中文场景下,如何准确理解文本的深层含义成为关键挑战。今天我们将深入对比两个在中文语义理解领域备受关注的模…...
yz-bijini-cosplay性能优化指南:GPU资源高效利用
yz-bijini-cosplay性能优化指南:GPU资源高效利用 1. 为什么需要GPU优化 当你运行yz-bijini-cosplay这类图像生成模型时,可能会遇到这样的情况:生成速度慢、图片分辨率上不去,甚至有时候程序直接崩溃报"显存不足"。这些…...
AI Agent Harness Engineering 的数据治理:输入输出的合规边界
AI Agent Harness Engineering 的数据治理:输入输出的合规边界 关键词:AI Agent、Harness Engineering、数据治理、合规边界、输入输出、数据安全、AI治理 摘要:随着AI Agent技术的快速发展,自主智能体在各行各业的应用越来越广泛,但随之而来的输入输出数据合规问题也日益…...
从零开始:MySQL安装与IDEA数据库连接实战指南
1. MySQL安装全流程详解 第一次接触MySQL的开发者往往会被复杂的安装过程劝退,但其实只要跟着步骤一步步来,半小时内就能搞定。我经历过无数次安装失败后总结出这套"保姆级"教程,帮你避开所有坑点。 1.1 下载MySQL的正确姿势 打开M…...
暗黑2存档编辑器终极指南:d2s-editor让你轻松掌控游戏体验
暗黑2存档编辑器终极指南:d2s-editor让你轻松掌控游戏体验 【免费下载链接】d2s-editor 项目地址: https://gitcode.com/gh_mirrors/d2/d2s-editor 你是否厌倦了反复刷装备的枯燥过程?想要体验不同职业build却受限于角色养成时间?d2s…...
