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;}
}

問題原因

問題的根本原因是deleteAllInBatchdeleteAll在執行刪除操作時的實現方式不同,導致生命周期回調方法(如@PreRemove)未被觸發。

deleteAllInBatchdeleteAll的區別

  1. deleteAll():該方法會逐個加載實體,并在JPA上下文中處理每個實體的刪除操作。每次刪除實體時,都會觸發實體的生命周期回調方法(如@PreRemove@PostRemove等)。因此,當使用deleteAll()方法時,你在實體類上定義的邏輯刪除(例如通過@PreRemove標記設置刪除標記)可以生效。

  2. 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字段來避免物理刪除。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/70940.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/70940.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/70940.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【Docker】使用Docker搭建-MySQL數據庫服務

零、更換Docker鏡像源 因為國內現在封鎖了Docker默認拉取鏡像的站點&#xff08;DockerHub&#xff09;&#xff0c;而且國內大部分Docker鏡像站已全部下線&#xff0c;導致現在很多朋友在拉取鏡像的時候會出現無法拉取的現象&#xff0c;這時候就需要進行更換Docker鏡像源。 可…

人類駕駛的人腦兩種判斷模式(反射和預判)-->自動駕駛兩種AI模式

一種模式是直覺模式&#xff0c;判斷基于條件反射&#xff0c;視覺感知 觸發到 直接條件反射&#xff08;從經歷中沉淀形成的神經信息閉環&#xff09;&#xff0c;類似現在自動駕駛技術的傳統AI模式&#xff1b;另一種是圖式推理模式&#xff0c;判斷是基于預判&#xff0c;人…

3.17 AI Agent 場景革命:解鎖企業級應用的 15 個黃金賽道

AI Agent 場景革命:解鎖企業級應用的 15 個黃金賽道 關鍵詞:AI Agent 應用場景, 企業級智能體案例, 多模態 Agent 實現, 工具鏈自動化, 智能決策系統 1. 企業級 Agent 場景分類圖譜 #mermaid-svg-UjUmmToEKigfdlFf {font-family:"trebuchet ms",verdana,arial,san…

Docker基礎-常見命令

docker images -查看所有的本地鏡像。 docker pull -把遠端鏡像拉取到本地。 docker rmi -刪除鏡像。 docker push -推到鏡像倉庫。 docker run -創建并運行容器&#xff08;自動化&#xff0c;如果發現鏡像不存在會先去拉取&#xff0c; 拉取完了以后再去自動創建容器&am…

TinyEngine v2.2版本發布:支持頁面嵌套路由,提升多層級路由管理能力開發分支調整

2025年春節假期已過&#xff0c;大家都帶著慢慢的活力回到了工作崗位。為了讓大家在新的一年繼續感受到 Tiny Engine 的成長與變化&#xff0c;我們很高興地宣布&#xff1a;TinyEngine v2.2版本正式發布&#xff01;本次更新帶來了重要的功能增強------頁面支持嵌套路由&#…

LSTM長短期記憶網絡-原理分析

1 簡介 概念 LSTM&#xff08;Long Short-Term Memory&#xff09;也稱為長短期記憶網絡&#xff0c;是一種改進的循環神經網絡&#xff08;RNN&#xff09;&#xff0c;專門設計用于解決傳統RNN的梯度消失問題和長程依賴問題。LSTM通過引入門機制和細胞狀態&#xff0c;能夠更…

SQL Server 中遇到的常見問題集

SQL Server 中遇到的常見問題集 問題一&#xff1a; 無法創建關系“FK_Research_Teacher”。 ALTER TABLE 語句與 FOREIGN KEY 約束"FK_Research_Teacher"沖突 解決方法&#xff1a; 外鍵表中的數據主鍵表中是有的&#xff0c;并且不能刪除主外鍵表中數據 1&…

神經網絡中感受野的概念和作用

在神經網絡中&#xff0c;感受野&#xff08;Receptive Field&#xff09;是指某個神經單元&#xff08;神經元或者卷積核&#xff09;關注的輸入特征區域的大小。它決定了神經網絡對輸入數據的特定區域的感知能力。 感受野的形成過程 在卷積神經網絡中&#xff0c;卷積層是感受…

unreal engine gameplay abiliity 獲取ability的cooldown剩余時間

unreal engine gameplay abiliity 獲取ability的cooldown 版本 5.4.4 參考 測試代碼 if (HasAuthority() && AbilitySystemComponent){TArray<FGameplayAbilitySpecHandle> OutAbilityHandles;AbilitySystemComponent->GetAllAbilities(OutAbilityHandles…

【leetcode hot 100 42】接雨水

錯誤解法&#xff1a;若height[left]>height[right]則代表有坑 class Solution {public int trap(int[] height) {int left 0;int area 0;while(left<height.length-1){// 找坑int right left1;while(right<height.length-1 && height[left]>height[ri…

Spark map與mapPartitions算子源碼級深度解析

Spark map與mapPartitions算子源碼級深度解析 一、核心源碼結構差異 1. map算子實現邏輯 def map[U: ClassTag](f: T => U): RDD[U] = withScope {val cleanF = sc.clean(f)new MapPartitionsRDD[U, T](this, (context, pid, iter) => iter.map(cleanF)) }實現特征: …

【前端進階】09 編程思維:從事件驅動到數據驅動

事件驅動與數據驅動 GUI與事件事件驅動數據驅動事件驅動和數據驅動的區別 GUI與事件 JavaScript作為瀏覽器的腳本語言&#xff0c;主要用途是與用戶互動、操作DOM&#xff0c;實現頁面UI和DOM操作&#xff0c;屬于GUI&#xff08;圖形用戶界面&#xff09;編程 GUI程序注重用…

WPF-3天快速WPF入門并達到企業級水準

嘿&#xff0c;小伙伴們&#xff01;如果你已經有一定的C#開發基礎&#xff0c;但想快速掌握WPF開發&#xff0c;達到企業級水準&#xff0c;那接下來的這個三天快速入門計劃絕對適合你&#xff01;雖然聽起來有點挑戰&#xff0c;但別擔心&#xff0c;只要跟著這個高強度、結構…

【實戰 ES】實戰 Elasticsearch:快速上手與深度實踐-1.3.1單節點安裝(Docker與手動部署)

&#x1f449; 點擊關注不迷路 &#x1f449; 點擊關注不迷路 &#x1f449; 點擊關注不迷路 文章大綱 10分鐘快速部署Elasticsearch單節點環境1. 系統環境要求1.1 硬件配置推薦1.2 軟件依賴 2. Docker部署方案2.1 部署流程2.2 參數說明2.3 性能優化建議 3. 手動部署方案3.1 安…

小程序中的插槽(Slot)機制及其與 Vue 組件的異同

小程序中的插槽&#xff08;Slot&#xff09;機制及其與 Vue 組件的異同 引言 在小程序開發中&#xff0c;組件化開發是一種重要的設計模式&#xff0c;而插槽&#xff08;Slot&#xff09;機制則是實現組件內容分發的關鍵。通過插槽&#xff0c;開發者可以更靈活地構建可復用…

vscode下載安裝教程(附安裝包)vscode圖文安裝教程最新版

文章目錄 一、vscode下載二、vscod安裝教程1.啟動vscode安裝程序&#xff1a;2.應對提示&#xff1a;3.接受協議&#xff1a;4.更改vscode安裝路徑&#xff1a;5.推進安裝vscode&#xff1a;6.創建vscode快捷方式&#xff1a;7.開始安裝vscode&#xff1a;8.完成vscode安裝&…

Redis 緩存穿透、擊穿、雪崩:問題與解決方案

在使用 Redis 作為緩存中間件時&#xff0c;系統可能會面臨一些常見的問題&#xff0c;如 緩存穿透、緩存擊穿 和 緩存雪崩。這些問題如果不加以解決&#xff0c;可能會導致數據庫壓力過大、系統響應變慢甚至崩潰。本文將詳細分析這三種問題的起因&#xff0c;并提供有效的解決…

智能客服進化論:AI呼叫中心系統如何重塑企業服務競爭力?

導語&#xff1a;當客戶咨詢量激增300%時&#xff0c;你的客服團隊還能從容應對嗎&#xff1f; 在數字化轉型加速的今天&#xff0c;企業客戶服務正經歷從"人力密集型"向"智能集約化"的質變。AI呼叫中心系統作為這場變革的核心引擎&#xff0c;已幫助超過…

異常c/c++

目錄 1.c語言傳統處理錯誤方式 1、終止程序 2、返回錯誤碼 2.c異常概念 3.異常的使用 3.1異常的拋出與捕獲 3.2異常安全&#xff08;還有一些異常重新拋出&#xff09; 3.3異常規范 4.自定義異常體系 5.c標準庫的異常體系 6.異常優缺點 1、優點 2、缺點 7、補充 1.…

ChatGPT 提示詞框架

作為一個資深安卓開發工程師&#xff0c;我們在日常開發中經常會用到 ChatGPT 來提升開發效率&#xff0c;比如代碼優化、bug 排查、生成單元測試等。 但要想真正發揮 ChatGPT 的潛力&#xff0c;我們需要掌握一些提示詞&#xff08;Prompt&#xff09;的編寫技巧&#xff0c;并…