这才是批量Update的正确姿态!

  • 电脑网络维修
  • 2024-11-15

最近我有位小同伴问我,在实践上班中,批量降级的代码要怎样写。

这个疑问挺有代表性的,当天拿进去给大家一同分享一下,宿愿对你会有所协助。

有一天上午,在我的常识星球群里,有位小同伴问了我一个疑问:批量降级你们普通是经常使用when case吗?还是有其余的批量降级方法?

我的回答是:我们星球的商城名目中,有批量降级的代码可以参考一下,这个名目中很多代码,大家往常可以多看看。

而后我将关键代码发到群里了,这是批量重置用户明码的业务场景:

<update parameterType="cn.net.susan.entity.sys.UserEntity"><foreach collection="list" item="entity" separator=";">UPDATE sys_userSET password = #{entity.password},update_user_id=#{entity.updateUserId},update_user_name=#{entity.updateUserName}<where>id = #{entity.id}</where></foreach></update>

有小同伴说,第一次性见到这种写法,涨常识了。

还有小同伴问,上方这种写法,跟间接for循环中update有什么区别?

for(UserEntity userEntity: list) {userMapper.update(userEntity);}

间接for循环须要屡次恳求数据库,网络有必定的开支,很显然没有批量一次性恳求数据库的好。

有小伙说,他之前不时都是用的case when的写法。

相似上方这样的:

<update parameterType="cn.net.susan.entity.sys.UserEntity">update sys_user<trim prefix="set" suffixOverrides=","><trim prefix="password = case id" suffix="end,"><foreach collection="list" item="item">when #{item.id} then #{item.password}</foreach></trim><trim prefix="update_user_id = case id" suffix="end,"><foreach collection="list" item="item">when #{item.id} then #{item.updateUserId}</foreach></trim><trim prefix="update_user_name = case id" suffix="end"><foreach collection="list" item="item">when #{item.id} then #{item.updateUserName}</foreach></trim></trim><where>id in (<foreach collection="list" separator="," item="item">#{item.id}</foreach>)</where></update>

但这种写法显然须要拼接很多条件,有点复杂,而且性能也不太好。

还有些文章中引见,可以经常使用在insert的时刻,可以在语句最后加上ON DUPLICATE KEY UPDATE关键字。

<update parameterType="cn.net.susan.entity.sys.UserEntity">insert into sys_user(id,username,password) values<foreach collection="list" index="index" item="item" separator=",">(#{item.id},#{item.username},#{item.password})</foreach>ON DUPLICATE KEY UPDATEpassword=values(password)</update>

在拔出数据时,数据库会先判别数据能否存在,假设不存在,则口头拔出操作。假设存在,则口头降级操作。

这种形式我之前也用过,普通须要创立惟一索引。

由于很多时刻主键id,是智能增长的或许依据雪花算法生成的,每次都不一样,没法辨别屡次相反业务参数恳求的惟一性。

因此,倡导创立一个惟一索引,来保障业务数据的惟一性。

比如:给username创立惟一索引,在insert的时刻,发现username已存在,则口头update操作,降级password。

这种形式批量降级数据,性能比拟好,但普通的大公司很少会用,由于十分容易发生死锁的疑问。

因此,目前批量降级数据最好的选用,还是我在文章扫尾引见的第一种方法。

群里另外一位小同伴,依照我的倡导,在自己的名目中尝试了一下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.DruidDataSourcedruid:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/console?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=trueusername: rootpassword: root

这个改变十分便捷。

但WallFilter中的校验疑问如何处置呢?

于是,我上网查了一下,可以经过参数调整druid中的filter的判别逻辑,比如:

spring:datasource:url: jdbc:xxx&serverTimeznotallow=Asia/Shanghai&rewriteBatchedStatements=true&allowMultiQueries=trueusername: xxxpassword: xxxdriver-class-name: com.mysql.cj.jdbc.Drivertype: com.alibaba.druid.pool.DruidDataSourcedruid:filter:wall:config:multi-statement-allow: truenone-base-statement-allow: true

经过设置filter中的multi-statement-allow和none-base-statement-allow为true,这样就能开启批量降级的性能。

普通经常使用druid的datasource性能,经过上方这样调整是OK的。

但有些小同伴发现,我们的商城名目中,经过上方的两个中央的修正,还是不时报上方的意外:

sql injection violation, multi-statement not allow

这是怎样回事呢?

答:我们商城名目中的订单表,经常使用shardingsphere做了分库分表,并且经常使用baomidou成功多个数据源灵活切换的性能:

<dependency><groupId>com.baomidou</groupId><artifactId>dynamic-datasource-spring-boot-starter</artifactId><version>3.1.1</version></dependency>

我们是经常使用了baomidou包下的数据源性能,这特性能在DynamicDataSourceProperties类中:

这个类是数据库的性能类,我们可以看到master和druid的性能是在同一层级的,于是,将application.yml文件中的性能改成上方这样的:

spring:application:name: mall-jobdatasource:dynamic:primary: masterdatasource:master:username: rootpassword: 123456url: jdbc:mysql://localhost:3306/susan_mall?serverTimeznotallow=Asia/Shanghai&characterEncoding=utf8&useSSL=false&zeroDateTimeBehavior=convertToNulldriver-class-name: com.mysql.cj.jdbc.Driverdruid:wall:multiStatementAllow: truenoneBaseStatementAllow: true

这样改变之后,商城名目中经常使用foreach这种批量降级数据的性能OK了。

本文由一位球友的疑问开局,探讨了批量降级的四种经常出现形式:

虽说有很多种形式,但我团体以为批量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: truenone-base-statement-allow: true

关键是multi-statement-allow设置成true。

假设你还经常使用了其余第三方的数据库两边件,比如我经常使用了baomidou成功多个数据源灵活切换的性能。

这时刻,须要检查它的源码,确认它multi-statement-allow的性能参数是怎样性能的,有或许跟druid不一样。

  • 关注微信

本网站的文章部分内容可能来源于网络和网友发布,仅供大家学习与参考,如有侵权,请联系站长进行删除处理,不代表本网站立场,转载联系作者并注明出处:https://duobeib.com/diannaowangluoweixiu/7619.html

猜你喜欢

热门标签

洗手盆如何疏浚梗塞 洗手盆为何梗塞 iPhone提价霸占4G市场等于原价8折 明码箱怎样设置明码锁 苏泊尔电饭锅保修多久 长城画龙G8253YN彩电输入指令画面变暗疑问检修 彩星彩电解除童锁方法大全 三星笔记本培修点上海 液晶显示器花屏培修视频 燃气热水器不热水要素 热水器不上班经常出现3种处置方法 无氟空调跟有氟空调有什么区别 norltz燃气热水器售后电话 大连站和大连北站哪个离周水子机场近 热水器显示屏亮显示温度不加热 铁猫牌保险箱高效开锁技巧 科技助力安保无忧 创维8R80 汽修 a1265和c3182是什么管 为什么电热水器不能即热 标致空调为什么不冷 神舟培修笔记本培修 dell1420内存更新 青岛自来水公司培修热线电话 包头美的洗衣机全国各市售后服务预定热线号码2024年修缮点降级 创维42k08rd更新 空调为什么运转异响 热水器为何会漏水 该如何处置 什么是可以自己处置的 重庆华帝售后电话 波轮洗衣机荡涤价格 鼎新热水器 留意了!不是水平疑问! 马桶产生了这5个现象 方便 极速 邢台空调移机电话上门服务 扬子空调缺点代码e4是什么疑问 宏基4736zG可以装置W11吗 奥克斯空调培修官方 为什么突然空调滴水很多 乐视s40air刷机包 未联络视的提高方向 官网培修 格力空调售后电话 皇明太阳能电话 看尚X55液晶电视进入工厂形式和软件更新方法 燃气热水器缺点代码

热门资讯

关注我们

微信公众号