Mybatis解決以某個字段存在,批量更新,不存在批量插入(高效)(一)

背景

在開發企業級應用時,我們經常需要處理批量數據的插入和更新操作。傳統的逐條處理方式性能低下,而簡單的REPLACE INTOINSERT ... ON DUPLICATE KEY UPDATE在某些場景下又不夠靈活。本文將介紹一種基于臨時表的高效批量插入/更新方案,解決復雜業務場景下的數據同步問題。

場景

這個表需要大量插入和更新數據,頻繁的比對浪費時間,且效率不高,要減少數據庫連接時間開銷。可以采用臨時表的方式進行插入更新。假設下表,根據username和age組合判斷記錄是否存在,存在則更新,不存在則插入。

整體設計邏輯

創建mapper接口

  /*** 批量插入或更新(根據username和age判斷)* @param list 批量數據列表* @return 影響的行數*/int batchInsertOrUpdateByUsernameAndAge(List<BatchTest> list);

創建mapper.xml

  <insert id="batchInsertOrUpdateByUsernameAndAge" parameterType="java.util.List"><!-- 創建臨時表存儲批量數據 -->CREATE TEMPORARY TABLE temp_batch_test (username varchar(50),age int,email varchar(100),status tinyint) ENGINE=MEMORY;<!-- 插入數據到臨時表 -->INSERT INTO temp_batch_test (username, age, email, status)VALUES<foreach collection="list" item="item" separator=",">(#{item.username}, #{item.age}, #{item.email}, #{item.status})</foreach>;<!-- 更新已存在的記錄(匹配username和age) -->UPDATE batch_test bJOIN temp_batch_test t ON b.username = t.username AND b.age = t.ageSETb.email = t.email,b.status = t.status;<!-- 插入新記錄(不存在的username和age組合) -->INSERT INTO batch_test (username, age, email, status)SELECT t.username, t.age, t.email, t.statusFROM temp_batch_test tLEFT JOIN batch_test b ON t.username = b.username AND t.age = b.ageWHERE b.username IS NULL;<!-- 刪除臨時表 -->DROP TEMPORARY TABLE IF EXISTS temp_batch_test;</insert>

更新和插入的邏輯

案例數據流程

初始數據(batch_test表)

idusernameageemailstatus
1張三25zhangsan@old.com1
2李四30lisi@old.com1

批量輸入數據(temp_batch_test表)

usernameageemailstatus
張三25zhangsan@new.com0
李四35lisi@new.com1
王五28wangwu@new.com1

操作結果

  1. 更新操作

    • 匹配記錄:張三(25歲)

    • 執行:UPDATE ... SET email='zhangsan@new.com', status=0

  2. 插入操作

    • 新記錄:李四(35歲)、王五(28歲)

    • 執行:INSERT INTO ... VALUES ('李四',35,...), ('王五',28,...)

最終數據

idusernameageemailstatus
1張三25zhangsan@new.com0← 更新
2李四30lisi@old.com1
3李四35lisi@new.com1← 新增
4王五28wangwu@new.com1← 新增

實現邏輯詳解

核心邏輯步驟

  1. 臨時表創建階段
    CREATE TEMPORARY TABLE temp_batch_test (username varchar(50),age int,email varchar(100),status tinyint
    ) ENGINE=MEMORY;
    • 使用MEMORY引擎提高臨時表操作速度

    • 只包含必要字段,減少內存占用

  2. 數據加載階段
    INSERT INTO temp_batch_test VALUES
    ('張三',25,'zhangsan@new.com',0),
    ('李四',35,'lisi@new.com',1),
    ('王五',28,'wangwu@new.com',1);
    • 使用MyBatis的foreach實現動態批插

    • 參數化查詢防止SQL注入

  3. 更新階段
    UPDATE batch_test b
    JOIN temp_batch_test t ON b.username = t.username AND b.age = t.age
    SET b.email = t.email, b.status = t.status;
  4. 插入階段(重點)

這是插入操作的核心技術,通過?LEFT JOIN + IS NULL?實現:

FROM temp_batch_test t
LEFT JOIN batch_test b ON t.username = b.username AND t.age = b.age
WHERE b.username IS NULL

執行過程:

  1. 左連接:將臨時表(t)與主表(b)按username和age進行連接

  2. 過濾:只保留主表中不存在的記錄(即b.username為NULL的記錄)

內存中的連接結果示例:

t.usernamet.aget.emailt.statusb.usernameb.ageb.email
張三25zhangsan@new.com0張三25...主表存在
李四35lisi@new.com1NULLNULLNULL主表不存在
王五28wangwu@new.com1NULLNULLNULL?主表不存在

WHERE條件過濾后結果:

t.usernamet.aget.emailt.status
李四35lisi@new.com1
王五28wangwu@new.com1
執行批量插入

將過濾后的結果插入主表:

INSERT INTO batch_test (username, age, email, status)
-- 上一步的查詢結果

執行效果等價于:

INSERT INTO batch_test (username, age, email, status) VALUES
('李四', 35, 'lisi@new.com', 1),
('王五', 28, 'wangwu@new.com', 1);

關鍵技術點解析

  1. 反連接(Anti-Join)模式

    • 通過LEFT JOIN + IS NULL實現"不存在于"的邏輯

    • 比NOT IN或NOT EXISTS性能更好,特別是大數據量時

  2. 復合條件判斷

    ON t.username = b.username AND t.age = b.age
    • 同時匹配username和age字段

    • 只有當兩個字段都相等時才認為是重復記錄

  3. NULL安全比較
    如果age可能為NULL,應該使用:

    ON t.username = b.username 
    AND (t.age = b.age OR (t.age IS NULL AND b.age IS NULL))
  4. 批量插入優勢

    • 單次SQL執行所有插入操作

    • 比循環執行單條INSERT效率高10-100倍

    • 減少網絡往返和SQL解析開銷

? ?清理階段
  1. 顯式釋放臨時表資源
  2. 避免連接池復用時的表沖突
  3. DROP TEMPORARY TABLE temp_batch_test;

實際執行案例

初始主表數據

idusernameageemailstatus備注
1張三25zhangsan@old.com1
2李四30lisi@old.com1

批量處理數據

usernameageemailstatus操作說明
張三25zhangsan@new.com0更新操作
李四35lisi@new.com1插入操作
王五28wangwu@new.com1插入操作

插入操作執行過程

  1. 臨時表與主表LEFT JOIN中間結果:

    臨時表數據主表匹配結果
    張三(25)匹配id=1的記錄
    李四(35)無匹配(NULL)
    王五(28)無匹配(NULL)
  2. 過濾后待插入數據:

    usernameageemailstatus
    李四35lisi@new.com1
    王五28wangwu@new.com1
  3. 最終主表數據:

    idusernameageemailstatus操作說明
    1張三25zhangsan@new.com0被更新
    2李四30lisi@old.com1
    3李四35lisi@new.com1新插入
    4王五28wangwu@new.com1新插入

性能優化建議

  1. 索引優化

    ALTER TABLE batch_test 
    ADD INDEX `idx_username_age` (`username`, `age`);
  2. 批量大小控制

    • 建議每批500-1000條記錄

    • 過大的批次可能導致內存問題

  3. 臨時表優化

    CREATE TEMPORARY TABLE ... (INDEX `idx_temp` (`username`, `age`)
    ) ENGINE=MEMORY;
  4. 服務器參數

    # my.cnf配置
    tmp_table_size = 256M
    max_heap_table_size = 256M

這種插入機制通過巧妙的SQL設計,實現了高效、準確的批量數據插入,是處理數據同步場景的理想解決方案。

必要配置

properties文件

# application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/dbname?allowMultiQueries=true
spring.datasource.hikari.connection-init-sql=SET SESSION sql_mode='NO_ENGINE_SUBSTITUTION'

測試數據:一定要自己動手試試

第一批數據(全部插入,status=1) - 20條

[{"username": "仇癸霖2", "age": 22, "email": "2244442", "status": 1},{"username": "靳浩然", "age": 33, "email": "hvbk3d38@vip.qq.com", "status": 1},{"username": "束雪", "age": 7, "email": "ssxtbf_ios@qq.com", "status": 1},{"username": "公孫雨", "age": 28, "email": "rain_gs@163.com", "status": 1},{"username": "歐陽明日", "age": 45, "email": "oymr@hotmail.com", "status": 1},{"username": "司馬青", "age": 19, "email": "smqing@126.com", "status": 1},{"username": "令狐沖", "age": 32, "email": "linghuchong@gmail.com", "status": 1},{"username": "東方不敗", "age": 40, "email": "dfbb@yeah.net", "status": 1},{"username": "西門吹雪", "age": 35, "email": "xmcx@sina.com", "status": 1},{"username": "慕容復", "age": 38, "email": "murongfu@qq.com", "status": 1},{"username": "趙靈兒", "age": 18, "email": "zle@163.com", "status": 1},{"username": "李逍遙", "age": 25, "email": "lxy@gmail.com", "status": 1},{"username": "林月如", "age": 22, "email": "lyr@126.com", "status": 1},{"username": "景天", "age": 30, "email": "jtian@qq.com", "status": 1},{"username": "唐雪見", "age": 27, "email": "txj@sina.com", "status": 1},{"username": "龍葵", "age": 20, "email": "lkui@163.com", "status": 1},{"username": "紫萱", "age": 300, "email": "zxuan@yeah.net", "status": 1},{"username": "徐長卿", "age": 35, "email": "xczq@hotmail.com", "status": 1},{"username": "重樓", "age": 500, "email": "chonglou@gmail.com", "status": 1},{"username": "花楹", "age": 15, "email": "huaying@qq.com", "status": 1}
]

第二批數據(混合更新和插入,更新status=0/新插入status=1) - 30條

[// 需要更新的記錄(username+age與第一批重復){"username": "仇癸霖2", "age": 22, "email": "new_2244442", "status": 0},{"username": "靳浩然", "age": 33, "email": "new_hvbk3d38@vip.qq.com", "status": 0},{"username": "束雪", "age": 7, "email": "new_ssxtbf_ios@qq.com", "status": 0},{"username": "公孫雨", "age": 28, "email": "new_rain_gs@163.com", "status": 0},{"username": "歐陽明日", "age": 45, "email": "new_oymr@hotmail.com", "status": 0},// 新插入的記錄{"username": "張無忌", "age": 28, "email": "zwj@mingjiao.org", "status": 1},{"username": "趙敏", "age": 25, "email": "zhaomin@yuandynasty.com", "status": 1},{"username": "周芷若", "age": 24, "email": "zzr@emei.org", "status": 1},{"username": "小昭", "age": 20, "email": "xiaozao@persia.com", "status": 1},{"username": "殷離", "age": 22, "email": "yinli@butterfly.com", "status": 1},{"username": "楊逍", "age": 40, "email": "yangxiao@mingjiao.org", "status": 1},{"username": "范遙", "age": 38, "email": "fanyao@mingjiao.org", "status": 1},{"username": "黛綺絲", "age": 42, "email": "daiqisi@persia.com", "status": 1},{"username": "謝遜", "age": 50, "email": "xiexun@lionking.com", "status": 1},{"username": "殷天正", "age": 60, "email": "yintianzheng@tiandihui.com", "status": 1},{"username": "韋一笑", "age": 45, "email": "weiyixiao@batman.com", "status": 1},{"username": "說不得", "age": 48, "email": "shuobude@monk.com", "status": 1},{"username": "冷謙", "age": 52, "email": "lengqian@cool.com", "status": 1},{"username": "彭瑩玉", "age": 55, "email": "pengyingyu@pearl.com", "status": 1},{"username": "周顛", "age": 50, "email": "zhoudian@crazy.com", "status": 1},{"username": "鐵冠道人", "age": 58, "email": "tieguandaoren@taoist.com", "status": 1},{"username": "朱元璋", "age": 35, "email": "zhuyuanzhang@emperor.com", "status": 1},{"username": "常遇春", "age": 38, "email": "changyuchun@general.com", "status": 1},{"username": "徐達", "age": 40, "email": "xuda@marshal.com", "status": 1},{"username": "湯和", "age": 42, "email": "tanghe@general.com", "status": 1},{"username": "鄧愈", "age": 37, "email": "dengyu@general.com", "status": 1},{"username": "沐英", "age": 30, "email": "muying@general.com", "status": 1},{"username": "藍玉", "age": 45, "email": "lanyu@general.com", "status": 1},{"username": "傅友德", "age": 50, "email": "fuyoude@general.com", "status": 1}
]

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

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

相關文章

JVM、JRE、JDK的區別

JVM JVM全稱Java虛擬機(Java Virtual Machine, JVM),它是運行java字節碼的虛擬機&#xff0c;JVM針對不同的系統有不同的實現&#xff0c;目的運行相同的字節碼有同樣的結果&#xff0c;JVM是“一次編譯&#xff0c;到處運行”實現的關鍵。如下不同的編程語言編譯生成字節碼文…

神經元和神經網絡定義

在深度學習中&#xff0c;神經元和神經網絡是構成神經網絡模型的基本元素。讓我們從基礎開始&#xff0c;逐步解釋它們的含義和作用。 1?? 神經元是什么&#xff1f; 神經元是神經網絡中的基本計算單元&#xff0c;靈感來自于生物神經系統中的神經元。每個人的腦中有數以億…

CDGP重點知識梳理

寫在前面 全文11700字,共82個重點知識 目 錄 考點分布 考試要求 第一章 數據管理-5%

Ubuntu 22.04 安裝配置遠程桌面環境指南

在云服務器或遠程主機上安裝圖形化桌面環境,可以極大地提升管理效率和用戶體驗。本文將詳細介紹如何在 Ubuntu 22.04 (Jammy Jellyfish) 系統上安裝和配置 Xfce4 桌面環境,并通過 VNC 實現遠程訪問。 系統環境 操作系統:Ubuntu 22.04 LTS (Jammy Jellyfish)架構:AMD64安裝…

node提示node:events:495 throw er解決方法

前言 之前開發的時候喜歡使用高版本&#xff0c;追求新的東西&#xff0c;然后回頭運行一下之前的項目提示如下 項目技術棧&#xff1a;node egg 報錯 node:events:495 throw er; // Unhandled error event ^ Error: ENOENT: no such file or directory, scandir F:\my\gi…

【軟件設計師:軟件工程】9.軟件開發模型與方法

一、軟件危機與軟件工程 軟件危機與軟件工程是計算機科學發展中密切相關的兩個概念。 1.軟件危機(Software Crisis) 背景:20世紀60年代至80年代,隨著計算機硬件性能提升,軟件規模與復雜度劇增,傳統開發方法難以應對,導致大量項目失敗。 表現: 成本失控:開發周期長、…

范式之殤-關系代數與參照完整性在 Web 后臺的落寞

最近參加了一個PostgreSQL相關的茶會&#xff0c;感慨良多。原本話題是PostgreSQL 在 SELECT 場景中憑借其成熟的查詢優化器、豐富的功能特性和靈活的執行策略&#xff0c;展現出顯著優勢。在窗口函數&#xff08;Window Functions&#xff09;、JOIN 優化、公共表表達式&#…

WebRTC工作原理詳細介紹、WebRTC信令交互過程和WebRTC流媒體傳輸協議介紹

簡介 WebRTC&#xff08;Web Real-Time Communication&#xff09;是一項允許在網頁瀏覽器之間進行音視頻通信的技術&#xff0c;基本不需要安裝額外的插件。它的核心特點是支持低延遲的點對點&#xff08;P2P&#xff09;通訊&#xff0c;常用于視頻聊天、實時文件共享、多人…

【大語言模型ChatGPT4/4o 】“AI大模型+”多技術融合:賦能自然科學暨ChatGPT在地學、GIS、氣象、農業、生態與環境領域中的應用

以ChatGPT、LLaMA、Gemini、DALLE、Midjourney、Stable Diffusion、星火大模型、文心一言、千問為代表AI大語言模型帶來了新一波人工智能浪潮&#xff0c;可以面向科研選題、思維導圖、數據清洗、統計分析、高級編程、代碼調試、算法學習、論文檢索、寫作、翻譯、潤色、文獻輔助…

提升編程效率的利器:Zed高性能多人協作代碼編輯器

在當今這個快節奏的開發環境中&#xff0c;一個高效、靈活的代碼編輯器無疑對開發者們起著至關重要的支持作用。Zed&#xff0c;作為來自知名編輯器Atom和語法解析器Tree-sitter的創造者的心血之作&#xff0c;正是這樣一款高性能支持多人合作的編輯神器。本文將帶領大家深入探…

基于51單片機步進電機控制—9個等級

基于51單片機步進電機控制 &#xff08;仿真&#xff0b;程序&#xff0b;設計報告&#xff09; 功能介紹 具體功能&#xff1a; 1.使用L298驅動步進電機轉動&#xff0c;可分為9個速度等級&#xff08;1級最快&#xff0c;9級最慢&#xff09;&#xff1b; 2.使用74HC595驅…

【某OTA網站】phantom-token 1004

新版1004 phantom-token 請求頭中包含phantom-token 定位到 window.signature 熟悉的vmp 和xhs一樣 最新環境檢測點 最新檢測 canvas 下的 toDataURL方法較嚴 過程中 會用setAttribute給canvas 設置width height 從而使toDataURL返回不同的值 如果寫死toDataURL的返回值…

LSTM的簡單模型

好的&#xff0c;我來用通俗易懂的語言解釋一下這個 LSTMTagger 類是如何工作的。 1?? 類的目的 這個 LSTMTagger 類是一個用于自然語言處理&#xff08;NLP&#xff09;任務的模型&#xff0c;目的是標注輸入的句子&#xff0c;通常用于詞性標注&#xff08;例如&#xff…

每天批次導入 100 萬對賬數據到 MySQL 時出現死鎖

一、死鎖原因及優化策略 1.1 死鎖原因分析 批量插入事務過大&#xff1a; Spring Batch 默認將整個 chunk&#xff08;批量數據塊&#xff09;作為一個事務提交&#xff0c;100 萬數據可能導致事務過長&#xff0c;增加鎖競爭。 并發寫入沖突&#xff1a; 多個線程或批處理作…

DeepResearch深度搜索實現方法調研

DeepResearch深度搜索實現方法調研 Deep Research 有三個核心能力 能力一&#xff1a;自主規劃解決問題的搜索路徑&#xff08;生成子問題&#xff0c;queries&#xff0c;檢索&#xff09;能力二&#xff1a;在探索路徑時動態調整搜索方向&#xff08;劉亦菲最好的一部電影是…

跟我學C++中級篇——STL容器的查找對比

一、C標準庫的查找 在C的STL中&#xff0c;對容器或相關序列的查找中&#xff0c;有兩種方式&#xff0c;一種是std::find&#xff0c;另外一種是std::search。而且在它們的基礎上&#xff0c;還衍生出std::find_if、std::find_if_not、std::find_end等和std::search_n、range…

SpringAI框架中的RAG知識庫檢索與增強生成模型詳解

SpringAI框架中的RAG知識庫檢索與增強生成模型詳解 一、RAG簡介 RAG&#xff08;Retrieval-Augmented Generation&#xff09;可以通過檢索知識庫&#xff0c;克服大模型訓練完成后參數凍結的局限性&#xff0c;攜帶知識讓大模型根據知識進行回答。 二、SpringAI框架支持的R…

Delphi12安裝Android開發的配置

Delphi12如果要開發android和Linux系統,需要在安裝的時候安裝這兩個選項,否則,就找不到開發平臺。 1、Adroid開發三劍客必須是指: JDK,SDK,NDK三洋,其中JDK是必須要安裝的,最好使用Installer安裝,否則自解壓的免安裝版在安裝過程中會退出。 2、開始安裝Delphi12. …

OpenHarmony launcher開發——刪除dock欄

開發環境 OpenHarmony 5.0.0 代碼修改 效果

FreeRTOS如何實現100%的硬實時性?

實時系統在嵌入式應用中至關重要&#xff0c;其核心在于確保任務在指定時間內完成。根據截止時間滿足的嚴格程度&#xff0c;實時系統分為硬實時和軟實時。硬實時系統要求任務100%滿足截止時間&#xff0c;否則可能導致災難性后果&#xff0c;例如汽車安全系統或醫療設備。軟實…