java的批量update
这个问题挺有代表性的,今天拿出来给大家一起分享一下,希望对你会有所帮助。
1 案发现场
有一天上午,在我的知识星球群里,有位小伙伴问了我一个问题:批量更新你们一般是使用when case吗?还是有其他的批量更新方法?
我的回答是:咱们星球的商城项目中,有批量更新的代码可以参考一下,这个项目中很多代码,大家平时可以多看看。
然后我将关键代码发到群里了,这是批量重置用户密码的业务场景:
UPDATE sys_user SET password = #{entity.password},update_user_id=#{entity.updateUserId},update_user_name=#{entity.updateUserName} id = #{entity.id} 有小伙伴说,第一次见到这种写法,涨知识了。还有小伙伴问,上面这种写法,跟直接for循环中update有什么区别?
for(UserEntity userEntity: list) {
userMapper.update(userEntity);
}
直接for循环需要多次请求数据库,网络有一定的开销,很显然没有批量一次请求数据库的好。
2 其他的批量更新写法
有小伙说,他之前一直都是用的case when的写法。
类似下面这样的:
update sys_user when #{item.id} then #{item.password} when #{item.id} then #{item.updateUserId} when #{item.id} then #{item.updateUserName} id in ( #{item.id} ) 但这种写法显然需要拼接很多条件,有点复杂,而且性能也不太好。还有些文章中介绍,可以使用在insert的时候,可以在语句最后加上ON DUPLICATE KEY UPDATE关键字。
insert into sys_user (id,username,password) values (#{item.id}, #{item.username}, #{item.password}) ON DUPLICATE KEY UPDATE password=values(password) 在插入数据时,数据库会先判断数据是否存在,如果不存在,则执行插入操作。如果存在,则执行更新操作。这种方式我之前也用过,一般需要创建唯一索引。
因为很多时候主键id,是自动增长的或者根据雪花算法生成的,每次都不一样,没法区分多次相同业务参数请求的唯一性。
因此,建议创建一个唯一索引,来保证业务数据的唯一性。
比如:给username创建唯一索引,在insert的时候,发现username已存在,则执行update操作,更新password。
这种方式批量更新数据,性能比较好,但一般的大公司很少会用,因为非常容易出现死锁的问题。
因此,目前批量更新数据最好的选择,还是我在文章开头介绍的第一种方法。
3 发现了一个问题
群里另外一位小伙伴,按照我的建议,在自己的项目中尝试了一下foreach的这种批量更新操作,但代码报了一个异常:
sql injection violation, multi-statement not allow
这个异常是阿里巴巴druid包的WallFilter中报出来了。
它里面有个checkInternal方法,会对sql语句做一些校验,如果不满足条件,就会抛异常:图片
而druid默认不支持一条sql语句中包含多个statement语句,例如:我们的批量update数据的场景。
此外,MySQL默认也是关闭批量更新数据的,不过我们可以在jdbc的url要上,添加字符串参数:&allowMultiQueries=true,开启批量更新操作。
比如:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/console?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true
username: root
password: root
这个改动非常简单。
但WallFilter中的校验问题如何解决呢?
于是,我上网查了一下,可以通过参数调整druid中的filter的判断逻辑,比如:
spring:
datasource:
url: jdbc:xxx&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true&allowMultiQueries=true
username: xxx
password: xxx
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
druid:
filter:
wall:
config:
multi-statement-allow: true
none-base-statement-allow: true
通过设置filter中的multi-statement-allow和none-base-statement-allow为true,这样就能开启批量更新的功能。
最近就业形势比较困难,为了感谢各位小伙伴对苏三一直以来的支持,我特地创建了一些工作内推群, 看看能不能帮助到大家。
你可以在群里发布招聘信息,也可以内推工作,也可以在群里投递简历找工作,也可以在群里交流面试或者工作的话题。
4 一直不生效
普通使用druid的datasource配置,通过上面这样调整是OK的。
但有些小伙伴发现,咱们的商城项目中,通过上面的两个地方的修改,还是一直报下面的异常:
sql injection violation, multi-statement not allow
这是怎么回事呢?
答:咱们商城项目中的订单表,使用shardingsphere做了分库分表,并且使用baomidou实现多个数据源动态切换的功能:
com.baomidou dynamic-datasource-spring-boot-starter 3.1.1 我们是使用了baomidou包下的数据源配置,这个配置在DynamicDataSourceProperties类中:/**
- Copyright © 2018 organization baomidou
- Licensed under the Apache License, Version 2.0 (the “License”);
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an “AS IS” BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
*/
package com.baomidou.dynamic.datasource.spring.boot.autoconfigure;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.druid.DruidConfig;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.hikari.HikariCpConfig;
import com.baomidou.dynamic.datasource.strategy.DynamicDataSourceStrategy;
import com.baomidou.dynamic.datasource.strategy.LoadBalanceDynamicDataSourceStrategy;
import com.baomidou.dynamic.datasource.toolkit.CryptoUtils;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
import org.springframework.core.Ordered;
import java.util.LinkedHashMap;
import java.util.Map;
/**
-
DynamicDataSourceProperties
-
@author TaoYu Kanyuxia
-
@see DataSourceProperties
-
@since 1.0.0
*/
@Slf4j
@Getter
@Setter
@ConfigurationProperties(prefix = DynamicDataSourceProperties.PREFIX)
public class DynamicDataSourceProperties {public static final String PREFIX = “spring.datasource.dynamic”;
public static final String HEALTH = PREFIX + “.health”;/**
- 必须设置默认的库,默认master
/
private String primary = “master”;
/* - 是否启用严格模式,默认不启动. 严格模式下未匹配到数据源直接报错, 非严格模式下则使用默认数据源primary所设置的数据源
/
private Boolean strict = false;
/* - 是否使用p6spy输出,默认不输出
/
private Boolean p6spy = false;
/* - 是否使用seata,默认不使用
/
private Boolean seata = false;
/* - 是否使用 spring actuator 监控检查,默认不检查
/
private boolean health = false;
/* - 每一个数据源
/
private Map<String, DataSourceProperty> datasource = new LinkedHashMap<>();
/* - 多数据源选择算法clazz,默认负载均衡算法
/
private Class<? extends DynamicDataSourceStrategy> strategy = LoadBalanceDynamicDataSourceStrategy.class;
/* - aop切面顺序,默认优先级最高
/
private Integer order = Ordered.HIGHEST_PRECEDENCE;
/* - Druid全局参数配置
/
@NestedConfigurationProperty
private DruidConfig druid = new DruidConfig();
/* - HikariCp全局参数配置
*/
@NestedConfigurationProperty
private HikariCpConfig hikari = new HikariCpConfig();
/**
- 全局默认publicKey
*/
private String publicKey = CryptoUtils.DEFAULT_PUBLIC_KEY_STRING;
}
这个类是数据库的配置类,我们可以看到master和druid的配置是在同一层级的,于是,将application.yml文件中的配置改成下面这样的:
- 必须设置默认的库,默认master
spring:
application:
name: mall-job
datasource:
dynamic:
primary: master
datasource:
master:
username: root
password: 123456
url: jdbc:mysql://localhost:3306/susan_mall?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false&zeroDateTimeBehavior=convertToNull
driver-class-name: com.mysql.cj.jdbc.Driver
druid:
wall:
multiStatementAllow: true
noneBaseStatementAllow: true
这样改动之后,商城项目中使用foreach这种批量更新数据的功能OK了。
5 最后
本文由一位球友的问题开始,讨论了批量更新的四种常见方式:
for循环中一条条更新
foreach拼接update语句后批量更新。
使用case when的方式做判断。
使用insert into on duplicate key update语法,批量插入或者批量更新。
虽说有很多种方式,但我个人认为批量update的最佳方式是第2种方式。
但需要需要的地方是,使用foreach做批量更新的时候,一次性更新的数据不宜太多,尽量控制在1000以内,这样更新的性能还是不错的。
如果需要更新的数据超过了1000,则需要分成多批更新。
此外,如果大家遇到执行批量update操作,不支持批量更新问题时:
sql injection violation, multi-statement not allow
首先要在数据库连接的url后面增加&allowMultiQueries=true参数,开启数据的批量更新操作。
如果使用了druid数据库驱动的,可以在配置文件中调整filter的参数。
spring:
datasource:
druid:
filter:
wall:
config:
multi-statement-allow: true
none-base-statement-allow: true
主要是multi-statement-allow设置成true。
如果你还使用了其他第三方的数据库中间件,比如我使用了baomidou实现多个数据源动态切换的功能。
这时候,需要查看它的源码,确认它multi-statement-allow的配置参数是怎么配置的,有可能跟druid不一样。
相关文章:
java的批量update
这个问题挺有代表性的,今天拿出来给大家一起分享一下,希望对你会有所帮助。 1 案发现场 有一天上午,在我的知识星球群里,有位小伙伴问了我一个问题:批量更新你们一般是使用when case吗?还是有其他的批量更…...
go语言连续监控事件并回调处理
前言 go语言中使用回调函数处理事件:事件监测部分(如无限循环中的事件检测逻辑)可以独立于具体的业务处理逻辑。这使得代码的各个部分更加清晰,易于理解和维护。如果需要更改事件处理的方式,只需要修改注册的回调函数…...

1.探索WebSocket:实时网络的心跳!
序言 你可能听说过"WebSokcet"这个词,感觉它好像很高深,但其实它是一个超级酷的小工具,让我们在Web应用里实现实时通信。想象一下,你可以像聊天一样,在浏览器和服务器之间来回“畅聊“,没有延迟…...

uniapp学习(010-2 实现抖音小程序上线)
零基础入门uniapp Vue3组合式API版本到咸虾米壁纸项目实战,开发打包微信小程序、抖音小程序、H5、安卓APP客户端等 总时长 23:40:00 共116P 此文章包含第113p的内容 文章目录 抖音小程序下载抖音开发者工具先去开发者工具里进行测试 抖音开放平台配置开始打包上传…...
测试和实施面试题收集
前端+测试+运维+算法综合 前端部分面试题 判断第二个日期比第一个日期大 如何用脚本判断用户输入的的字符串是下面的时间格式2004-11-21 必须要保证用户的输入是此格式,并且是时间,比如说月份不大于12等等,另外我需要用户输入两个,并且后一个要比前一个晚,只允许用JAVASCR…...

【Vue3】一文全览基础语法-案例程序及配图版
文章目录 Vue应用基本结构模块化开发ref和reactive绑定事件 v-on 简写显示和隐藏 v-show条件渲染 v-if动态属性绑定 v-bind 简写:遍历数组或对象 v-for双向数据绑定 v-model渲染数据 v-text 和 v-html计算属性 computed侦听器 watch自动侦听器 watchEffect 本文示例…...
【OpenSearch】安装部署OpenSearch和OpenSearch-Dashboard
一、安装OpenSearch 1.禁用主机swap提高性能 sudo swapoff -a2.增加OpenSearch可用的内存映射数量。 编辑sysctl配置文件 sudo vi /etc/sysctl.conf在文件中添加一行来定义所需的值, 或者如果键存在,则更改值,然后保存您的更改。 vm.max…...
【系统架构设计师】2023年真题论文: 论软件可靠性评价的设计与实现(包括和素材和论文)
更多内容请见: 备考系统架构设计师-专栏介绍和目录 文章目录 真题题目(2023年 试题3)论文素材参考论文参考摘要正文总结真题题目(2023年 试题3) 软件可靠性评价是利用可靠性数学模型、统计技术等,对软件失效数据进行处理,评估和预测软件可靠性的过程,包括选择模型、收集数…...

教程:使用 InterBase Express 访问数据库(二)
1. 添加数据模块(IBX 通用教程) 本节将创建一个数据模块(TDataModule),这是一种包含应用程序使用的非可视组件的表单。 以下是完全配置好的 TDataModule 的视图: 创建 TDataModule 后,您可以在其他表单中使用这个数据模块。 2. 添加 TDataModule 要将数据模块添加到…...

Windows密码的网络认证---基于挑战响应认证的NTLM协议
一,网络认证NTLM协议简介 在平时的测试中,经常会碰到处于工作组的计算机,处于工作组的计算机之间是无法建立一个可信的信托机构的,只能是点对点进行信息的传输。 举个例子就是,主机A想要访问主机B上的资源,…...
fpga 常量无法改变
parameter LED_ON_PERIOD0 n0*CLOCK_FREQ; parameter LED_OFF_PERIOD0 (2-n0)*CLOCK_FREQ;这种代码的变量不会无法内部修改 需要改成reg形式并在这种逻辑里面修改变量 always (posedge clk_ref or negedge sys_rst_n) begin虽然是并行逻辑 但是变量尽量还是先赋值从硬件上并…...

【HarmonyOS NEXT】如何给未知类型对象定义类型并使用递归打印所有的Key
关键词:嵌套对象、类型、递归、未知类型 目录 使用 Record 与 ESObject 定义未知对象类型 递归打印未知类型对象的key 在鸿蒙应用开发中,所有的数据都必须定义类型,且不存在 any 类型,那么我们当遇到 key 值可能随时变化的情况…...

RuoYi 样例框架运行步骤(测试项目自用,同学可自取)
目录 后台 API 运行导入,下载包端口号mysql 准备运行 PC(电脑端)运行安装 nodejs安装 yarn 及其依赖,启动服务登录admin(admin123) 或 ry(admin123) App(移动)运行下载 HBuilderX运行app运行注意࿱…...
Java进程CPU飙高排查
一、首先通过top指令查看当前占用CPU较高的进程pid 二、查看当前进程消耗资源的线程PID: top -Hp pid 使用 top -Hp <pid> 命令(pid为Java进程的id号)查看该Java进程内所有线程的资源占用情况。 三、通过print命令将线程pid转为16进…...
conda的对应环境下安装cuda11.0和对应的cudnn
在 Conda 环境中安装 CUDA 11.0 和对应的 cuDNN,可以按照以下步骤进行: 一. 环境配置 1. 创建 Conda 环境 首先,创建一个新的 Conda 环境(可选): conda create -n myenv python3.8 conda activate myen…...

微服务透传日志traceId
问题 在微服务架构中,一次业务执行完可能需要跨多个服务,这个时候,我们想看到业务完整的日志信息,就要从各个服务中获取,即便是使用了ELK把日志收集到一起,但如果不做处理,也是无法完整把一次业…...
【自然语言处理与大模型】大模型(LLM)基础知识②
(1)LLaMA输入句子的长度理论上可以无限长吗? 理论上来说,LLM大模型可以处理任意长度的输入句子,但实际上存在一些限制。下面是一些需要考虑的因素: 1. 计算资源:生成长句子需要更多的计算资源&a…...

新能源汽车的未来:车载电源与V2G技术的前景
近年来,新能源汽车在全球市场上发展迅速,尤其是在中国,新能源汽车的月销量已经超过了燃油车。随着新能源技术的不断发展,新能源汽车不仅仅是作为出行工具,而逐渐成为“移动能源站”。本文将探讨电动汽车的车载外放电功…...

Git 本地操作(2)
会以下操作就可以完成本地的版本控制了,就不需要再复制文件每次改一个东西就复制整个工程保存下来啦! 建议先看上一篇文章噢 !!! 一、新建项目git本地操作 1、初始化仓库 创建一个 project 文件夹,将需…...

项目管理软件:5款甘特图工具测评
在项目管理中,甘特图作为一种直观且高效的任务进度展示工具,被广泛应用于各个行业。以下是几款功能强大、易于使用的甘特图工具,它们能够帮助项目经理更好地规划、跟踪和管理项目进度。 1、进度猫 进度猫是国内项目管理新秀,是…...

Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...
Java如何权衡是使用无序的数组还是有序的数组
在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路
进入2025年以来,尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断,但全球市场热度依然高涨,入局者持续增加。 以国内市场为例,天眼查专业版数据显示,截至5月底,我国现存在业、存续状态的机器人相关企…...
连锁超市冷库节能解决方案:如何实现超市降本增效
在连锁超市冷库运营中,高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术,实现年省电费15%-60%,且不改动原有装备、安装快捷、…...

Python爬虫(一):爬虫伪装
一、网站防爬机制概述 在当今互联网环境中,具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类: 身份验证机制:直接将未经授权的爬虫阻挡在外反爬技术体系:通过各种技术手段增加爬虫获取数据的难度…...

Springboot社区养老保险系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,社区养老保险系统小程序被用户普遍使用,为方…...

uniapp 开发ios, xcode 提交app store connect 和 testflight内测
uniapp 中配置 配置manifest 文档:manifest.json 应用配置 | uni-app官网 hbuilderx中本地打包 下载IOS最新SDK 开发环境 | uni小程序SDK hbulderx 版本号:4.66 对应的sdk版本 4.66 两者必须一致 本地打包的资源导入到SDK 导入资源 | uni小程序SDK …...
【安全篇】金刚不坏之身:整合 Spring Security + JWT 实现无状态认证与授权
摘要 本文是《Spring Boot 实战派》系列的第四篇。我们将直面所有 Web 应用都无法回避的核心问题:安全。文章将详细阐述认证(Authentication) 与授权(Authorization的核心概念,对比传统 Session-Cookie 与现代 JWT(JS…...

02.运算符
目录 什么是运算符 算术运算符 1.基本四则运算符 2.增量运算符 3.自增/自减运算符 关系运算符 逻辑运算符 &&:逻辑与 ||:逻辑或 !:逻辑非 短路求值 位运算符 按位与&: 按位或 | 按位取反~ …...

基于江科大stm32屏幕驱动,实现OLED多级菜单(动画效果),结构体链表实现(独创源码)
引言 在嵌入式系统中,用户界面的设计往往直接影响到用户体验。本文将以STM32微控制器和OLED显示屏为例,介绍如何实现一个多级菜单系统。该系统支持用户通过按键导航菜单,执行相应操作,并提供平滑的滚动动画效果。 本文设计了一个…...