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.mzph.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;例如汽车安全系统或医疗设备。软实…