当前位置: 首页 > news >正文

【精品】通用Mapper 批量更新bug解决方案

问题描述

环境:mysql8.x+mybatis3.5.13+tk.mybatis4.2.3

在使用tk.mybatis做批量更新时,程序会报错,说是执行的SQL语法错误,经研究源代码发现tk.mybatis在实现批量更新时是通过多次执行update语句实现的。这本身就不符合MySQL批量更新的语法,可以通过自定义Mapper的方式解决。

有关MySQL批量更新SQL语句的语法请参考:MySQL专有的SQL语句

解决方案

批量更新

  • 接口
@RegisterMapper
public interface BatchUpdateByIdMapper<T> {/*** 批量更新* @param list* @return*/@UpdateProvider(type = BatchUpdateByIdProvider.class, method = "dynamicSQL")int batchUpdate(List<T> list);
}
  • provider
public class BatchUpdateByIdProvider extends MapperTemplate {public BatchUpdateByIdProvider(Class<?> mapperClass, MapperHelper mapperHelper) {super(mapperClass, mapperHelper);}public String batchUpdate(MappedStatement statement) {//1.获取实体类对应的Class对象Class<?> entityClass = super.getEntityClass(statement);//2.获取实体类在数据库中对应的表名String tableName = super.tableName(entityClass);//3.生成update子句String update = SqlHelper.updateTable(entityClass, tableName);//4.创建StringBuilder用于拼接SQL语句的各个组成部分StringBuilder sb = new StringBuilder(update);sb.append("<trim prefix=\"set\" suffixOverrides=\",\">");//5.获取所有字段信息Set<EntityColumn> columns = EntityHelper.getColumns(entityClass);//获取主键EntityColumn pkEntityColumn = null;for (EntityColumn entityColumn : columns) {boolean isPrimaryKey = entityColumn.isId();if (isPrimaryKey) {pkEntityColumn = entityColumn;break;}}for (EntityColumn entityColumn : columns) {boolean isPrimaryKey = entityColumn.isId();//6.判断当前字段是否为主键if (!isPrimaryKey) {//7.使用非主键字段拼接SET子句String columnHolder = entityColumn.getColumnHolder("item");sb.append("<trim prefix=\"").append(entityColumn.getColumn()).append("= case\" suffix=\"end, \">");sb.append("<foreach collection=\"list\" index=\"index\" item=\"item\">");sb.append(" when ").append(pkEntityColumn.getColumn()).append(" = ").append(pkEntityColumn.getColumnHolder("item")).append(" then ").append(columnHolder);sb.append("</foreach>");sb.append("</trim>");}}sb.append("</trim>");//10.使用前面缓存的主键名、主键值拼接where子句sb.append("where ").append(pkEntityColumn.getColumn()).append(" in ");sb.append("<foreach close=\")\" collection=\"list\" item=\"item\" open=\"(\" separator=\", \">");sb.append(" #{item.").append(pkEntityColumn.getProperty()).append("}");sb.append("</foreach>");//11.将拼接好的字符串返回return sb.toString();}}

选择性批量更新

  • Mapper接口
@RegisterMapper
public interface BatchUpdateSelectiveByIdMapper<T> {/*** 选择性批量更新* @param list* @return*/@UpdateProvider(type = BatchUpdateSelectiveByIdProvider.class, method = "dynamicSQL")int batchUpdateSelective(List<T> list);
}
  • provider
public class BatchUpdateSelectiveByIdProvider extends MapperTemplate {public BatchUpdateSelectiveByIdProvider(Class<?> mapperClass, MapperHelper mapperHelper) {super(mapperClass, mapperHelper);}/*** 批量更新* @param statement* @return*/public String batchUpdateSelective(MappedStatement statement) {//1.获取实体类对应的Class对象Class<?> entityClass = super.getEntityClass(statement);//2.获取实体类在数据库中对应的表名String tableName = super.tableName(entityClass);//3.生成update子句String update = SqlHelper.updateTable(entityClass, tableName);//4.创建StringBuilder用于拼接SQL语句的各个组成部分StringBuilder sb = new StringBuilder(update);sb.append("<trim prefix=\"set\" suffixOverrides=\",\">");//5.获取所有字段信息Set<EntityColumn> columns = EntityHelper.getColumns(entityClass);//获取主键EntityColumn pkEntityColumn = null;for (EntityColumn entityColumn : columns) {boolean isPrimaryKey = entityColumn.isId();if (isPrimaryKey) {pkEntityColumn = entityColumn;break;}}for (EntityColumn entityColumn : columns) {boolean isPrimaryKey = entityColumn.isId();//6.判断当前字段是否为主键if (!isPrimaryKey) {//7.使用非主键字段拼接SET子句String columnHolder = entityColumn.getColumnHolder("item");sb.append("<trim prefix=\"").append(entityColumn.getColumn()).append("= case\" suffix=\"end, \">");sb.append("<foreach collection=\"list\" index=\"index\" item=\"item\">");sb.append("<if test=\"item.").append(entityColumn.getProperty()).append(" != null\"> ");sb.append(" when ").append(pkEntityColumn.getColumn()).append(" = ").append(pkEntityColumn.getColumnHolder("item")).append(" then ").append(columnHolder);sb.append(" </if>");sb.append("</foreach>");sb.append("</trim>");}}sb.append("</trim>");//10.使用前面缓存的主键名、主键值拼接where子句sb.append("where ").append(pkEntityColumn.getColumn()).append(" in ");sb.append("<foreach close=\")\" collection=\"list\" item=\"item\" open=\"(\" separator=\", \">");sb.append(" #{item.").append(pkEntityColumn.getProperty()).append("}");sb.append("</foreach>");//11.将拼接好的字符串返回return sb.toString();}}

测试代码

@Test
void batchUpdate(){List<Subject> list = List.of(Subject.builder().id(13L).name("111").build(),Subject.builder().id(14L).name("222").build(),Subject.builder().id(15L).name("333").build(),Subject.builder().id(16L).name("444").build());subjectMapper.batchUpdateSelective(list);
}

相关文章:

【精品】通用Mapper 批量更新bug解决方案

问题描述 环境&#xff1a;mysql8.xmybatis3.5.13tk.mybatis4.2.3 在使用tk.mybatis做批量更新时&#xff0c;程序会报错&#xff0c;说是执行的SQL语法错误&#xff0c;经研究源代码发现tk.mybatis在实现批量更新时是通过多次执行update语句实现的。这本身就不符合MySQL批量…...

腾讯mini项目-【指标监控服务重构-会议记录】2023-07-06

7/6 会议记录 Profile4个步骤 解压kafka消息初始化性能事件&#xff0c;分析事件将数据写入kafkaRun 开始执行各stage handler 上报耗时到otel-collector。。。 // ConsumerDispatchHandler consumer // // param msg *sarama.ConsumerMessage // param consumer *databus.K…...

【React】函数式组件和类式组件的用法和逻辑

组件的使用 当应用是以多组件的方式实现&#xff0c;这个应用就是一个组件化的应用 注意&#xff1a; 组件名必须是首字母大写虚拟DOM元素只能有一个根元素虚拟DOM元素必须有结束标签 < /> 渲染类组件标签的基本流程React 内部会创建组件实例对象调用render()得到虚拟 …...

题目 1061: 二级C语言-计负均正

从键盘输入任意20个整型数&#xff0c;统计其中的负数个数并求所有正数的平均值。 保留两位小数 样例输入 1 2 3 4 5 6 7 8 9 10 -1 -2 -3 -4 -5 -6 -7 -8 -9 -10 样例输出 10 5.50 解题思路&#xff1a; 如题所示&#xff0c;输入20个正负数&#xff0c;---》求付数的个…...

数位和(C++)

系列文章目录 进阶的卡莎C++_睡觉觉觉得的博客-CSDN博客数1的个数_睡觉觉觉得的博客-CSDN博客双精度浮点数的输入输出_睡觉觉觉得的博客-CSDN博客足球联赛积分_睡觉觉觉得的博客-CSDN博客大减价(一级)_睡觉觉觉得的博客-CSDN博客小写字母的判断_睡觉觉觉得的博客-CSDN博客纸币(…...

[牛客复盘] 牛客周赛round13 20230924

[牛客复盘] 牛客周赛round13 20230924 总结矩阵转置置2. 思路分析3. 代码实现 小红买基金1. 题目描述2. 思路分析3. 代码实现 小红的密码修改1. 题目描述2. 思路分析3. 代码实现 小红的转账设置方式1. 题目描述2. 思路分析3. 代码实现 小红打boss1. 题目描述2. 思路分析3. 代码…...

mybatsi-MyBatis的逆向工程

mybatsi-MyBatis的逆向工程 一、前言二、创建逆向工程的步骤1.添加依赖和插件2.创建MyBatis的核心配置文件3.创建逆向工程的配置文件4.执行MBG插件的generate目标 一、前言 正向工程&#xff1a;先创建Java实体类&#xff0c;由框架负责根据实体类生成数据库表。 Hibernate是支…...

转转闲鱼交易猫链接源码 支持二维码收款

最新仿二手闲置链接源码 后台一键生成链接&#xff0c;后台管理教程&#xff1a;解压源码&#xff0c;修改数据库config/Congig 不会可以看源码里有教程 下载程序&#xff1a;https://pan.baidu.com/s/16lN3gvRIZm7pqhvVMYYecQ?pwd6zw3...

Python爬虫基础(三):使用Selenium动态加载网页

文章目录 系列文章索引一、Selenium简介1、什么是selenium&#xff1f;2、为什么使用selenium3、安装selenium&#xff08;1&#xff09;谷歌浏览器驱动下载安装&#xff08;2&#xff09;安装selenium 二、Selenium使用1、简单使用2、元素定位3、获取元素信息4、交互 三、Phan…...

Linux系统下安装Mysql

1、执行命令&#xff1a;rpm -qa | grep -i mysql&#xff0c;先查看系统之前是否有安装相关的rpm包&#xff0c;如果有&#xff0c;会显示类似下面的信息&#xff1b; 2、通过命令yum -y remove mysql-*  一次性删除系统上所有相关的rpm包&#xff0c;或者通过命令yum -y …...

Jenkins学习笔记1

CI 服务器&#xff1a; 认识Jenkins&#xff1a; Jenkins是一个可扩展的持续集成&#xff08;CI&#xff09;引擎&#xff0c;是一个开源项目&#xff0c;旨在提供一个开放易用的软件平台&#xff0c;使得软件持续集成变成可能。Jenkins非常易于安装和配置&#xff0c;简单易…...

注意力机制

概念没什么好说的&#xff0c;反正大家都会说&#xff0c;具体实战怎么写才是最为重要的 1.自注意力 假设有一组数据&#xff0c;都是一维的向量&#xff0c;这个向量可能是一个样本&#xff0c;可能是其他什么&#xff0c;都无所谓。 假设有一组一维向量x1,x2,x3,x4,x5; 第…...

JVM-Java字节码技术笔记

Java字节码技术 Java字节码是java代码编译后的中间代码格式&#xff0c;JVM需要读取并解析字节码才能执行相应的任务 获取字节码简介&#xff1a;由单字节(byte)的指令组成 操作码&#xff08; 指令&#xff09;, 主要由类型前缀和操作名称两部分组成。根据指令的性质&#xf…...

C++ 友元、重载、继承、多态

友元 关键字&#xff1a;friend 友元的三种实现 全局函数做友元类做友元成员函数做友元 全局函数做友元 //建筑物类 class Building {//goodGay全局函数是Building好朋友&#xff0c;可以访问Building中私有成员friend void goodGay(Building& building); public:Build…...

Spring Boot 日志文件

前言 本篇博客主要介绍自定义的日志打印、日志的级别高低、如何保存日志等等..... 一、日志是什么&#xff1f;日志有什么用&#xff1f; 日志就是我们控制台上输出的内容&#xff0c;控制台上的输出的信息就是日志信息&#xff0c;如下所示&#xff1a; 日志有什么用&#x…...

vulhub venom

文章目录 靶场环境信息收集ftp服务二、信息利用三、任意文件上传三 sudo提权靶场环境 `vmware 靶场信息:https://www.vulnhub.com/entry/venom-1,701/ 下载地址:https://download.vulnhub.com/venom/venom.zip 新建虚拟机打开下载后的ovf文件 遇见导入失败合规性检查时,重试…...

量化交易之One Piece篇 - linux - 定时任务(重启服务器、执行程序、验证)

linux 执行命令: crontab -e 0 5 * * 1-5 sudo /sbin/shutdown -r now 0 17 * * 1-5 sudo /sbin/shutdown -r now 45 8 * * 1-5 cd /home/ubuntu/onepiece/bin/datacore && ./datacore 45 20 * * 1-5 cd /home/ubuntu/onepiece/bin/datacore && ./datacore 以…...

Qt5开发及实例V2.0-第二十三章-Qt-多功能文档查看器实例

Qt5开发及实例V2.0-第二十三章-Qt-多功能文档查看器实例 第23章 多功能文档查看器实例23.1. 简介23.2. 界面与程序框架设计23.2.1. 图片资源23.2.2. 网页资源23.2.3. 测试用文件 23.3 主程序代码框架23.4 浏览网页功能实现23.4.1 实现HtmIHandler处理器 23.5. 部分代码实现23.5…...

爬虫笔记_

爬虫简介 爬虫初始深入 爬虫在使用场景中的分类 通用爬虫&#xff1a; 抓取系统重要组成部分。抓取的是一整张页面数据 聚焦爬虫&#xff1a; 是建立在通用爬虫的基础上。抓取的是页面中特定的局部内容。 增量式爬虫 监测网站中数据更新的情况。只会抓取网站中最新更新出来的…...

Spring设计模式,事务管理和代理模式的应用

扩充&#xff1a;贝叶斯定理答案见底。 设计模式对关于面向对象问题的具体解决方案&#xff0e; 1&#xff0c;单例多例 在设计单例模式时&#xff0c;要注意两个点 1.构造方法要私有 2.成员变量要私有 3.创建对象所用的方法要被synchronized修饰.(因为方法体中会涉及到判断当…...

【kafka】Golang实现分布式Masscan任务调度系统

要求&#xff1a; 输出两个程序&#xff0c;一个命令行程序&#xff08;命令行参数用flag&#xff09;和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽&#xff0c;然后将消息推送到kafka里面。 服务端程序&#xff1a; 从kafka消费者接收…...

day52 ResNet18 CBAM

在深度学习的旅程中&#xff0c;我们不断探索如何提升模型的性能。今天&#xff0c;我将分享我在 ResNet18 模型中插入 CBAM&#xff08;Convolutional Block Attention Module&#xff09;模块&#xff0c;并采用分阶段微调策略的实践过程。通过这个过程&#xff0c;我不仅提升…...

YSYX学习记录(八)

C语言&#xff0c;练习0&#xff1a; 先创建一个文件夹&#xff0c;我用的是物理机&#xff1a; 安装build-essential 练习1&#xff1a; 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件&#xff0c;随机修改或删除一部分&#xff0c;之后…...

Qt Http Server模块功能及架构

Qt Http Server 是 Qt 6.0 中引入的一个新模块&#xff0c;它提供了一个轻量级的 HTTP 服务器实现&#xff0c;主要用于构建基于 HTTP 的应用程序和服务。 功能介绍&#xff1a; 主要功能 HTTP服务器功能&#xff1a; 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文全面剖析RNN核心原理&#xff0c;深入讲解梯度消失/爆炸问题&#xff0c;并通过LSTM/GRU结构实现解决方案&#xff0c;提供时间序列预测和文本生成…...

Mac下Android Studio扫描根目录卡死问题记录

环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中&#xff0c;提示一个依赖外部头文件的cpp源文件需要同步&#xff0c;点…...

使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台

🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...

laravel8+vue3.0+element-plus搭建方法

创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...

算法:模拟

1.替换所有的问号 1576. 替换所有的问号 - 力扣&#xff08;LeetCode&#xff09; ​遍历字符串​&#xff1a;通过外层循环逐一检查每个字符。​遇到 ? 时处理​&#xff1a; 内层循环遍历小写字母&#xff08;a 到 z&#xff09;。对每个字母检查是否满足&#xff1a; ​与…...

宇树科技,改名了!

提到国内具身智能和机器人领域的代表企业&#xff0c;那宇树科技&#xff08;Unitree&#xff09;必须名列其榜。 最近&#xff0c;宇树科技的一项新变动消息在业界引发了不少关注和讨论&#xff0c;即&#xff1a; 宇树向其合作伙伴发布了一封公司名称变更函称&#xff0c;因…...