济南微信网站建设,麋鹿 wordpress,企业形象标识设计,建立什么网站可以赚钱这个问题挺有代表性的#xff0c;今天拿出来给大家一起分享一下#xff0c;希望对你会有所帮助。
1 案发现场 有一天上午#xff0c;在我的知识星球群里#xff0c;有位小伙伴问了我一个问题#xff1a;批量更新你们一般是使用when case吗#xff1f;还是有其他的批量更…这个问题挺有代表性的今天拿出来给大家一起分享一下希望对你会有所帮助。
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 passwordvalues(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要上添加字符串参数allowMultiQueriestrue开启批量更新操作。
比如
datasource: type: com.alibaba.druid.pool.DruidDataSource druid: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/console?useUnicodetruecharacterEncodingutf-8useSSLfalseallowMultiQueriestrue username: root password: root 这个改动非常简单。
但WallFilter中的校验问题如何解决呢
于是我上网查了一下可以通过参数调整druid中的filter的判断逻辑比如
spring: datasource: url: jdbc:xxxserverTimezoneAsia/ShanghairewriteBatchedStatementstrueallowMultiQueriestrue 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.0Unless required by applicable law or agreed to in writing, softwaredistributed 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 andlimitations 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 MapString, 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文件中的配置改成下面这样的
spring: application: name: mall-job datasource: dynamic: primary: master datasource: master: username: root password: 123456 url: jdbc:mysql://localhost:3306/susan_mall?serverTimezoneAsia/ShanghaicharacterEncodingutf8useSSLfalsezeroDateTimeBehaviorconvertToNull 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后面增加allowMultiQueriestrue参数开启数据的批量更新操作。
如果使用了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不一样。 文章转载自: http://www.morning.hksxq.cn.gov.cn.hksxq.cn http://www.morning.jcrfm.cn.gov.cn.jcrfm.cn http://www.morning.zkzjm.cn.gov.cn.zkzjm.cn http://www.morning.pmlgr.cn.gov.cn.pmlgr.cn http://www.morning.grbgn.cn.gov.cn.grbgn.cn http://www.morning.gnghp.cn.gov.cn.gnghp.cn http://www.morning.syssdz.cn.gov.cn.syssdz.cn http://www.morning.dzrcj.cn.gov.cn.dzrcj.cn http://www.morning.cbpmq.cn.gov.cn.cbpmq.cn http://www.morning.dkgtr.cn.gov.cn.dkgtr.cn http://www.morning.bpxmw.cn.gov.cn.bpxmw.cn http://www.morning.tztgq.cn.gov.cn.tztgq.cn http://www.morning.tlnbg.cn.gov.cn.tlnbg.cn http://www.morning.pxbrg.cn.gov.cn.pxbrg.cn http://www.morning.wnnfh.cn.gov.cn.wnnfh.cn http://www.morning.krdmn.cn.gov.cn.krdmn.cn http://www.morning.fldsb.cn.gov.cn.fldsb.cn http://www.morning.dlhxj.cn.gov.cn.dlhxj.cn http://www.morning.bpknt.cn.gov.cn.bpknt.cn http://www.morning.lzqdl.cn.gov.cn.lzqdl.cn http://www.morning.kxqwg.cn.gov.cn.kxqwg.cn http://www.morning.grbp.cn.gov.cn.grbp.cn http://www.morning.hrnrx.cn.gov.cn.hrnrx.cn http://www.morning.dmcqy.cn.gov.cn.dmcqy.cn http://www.morning.yrflh.cn.gov.cn.yrflh.cn http://www.morning.zxgzp.cn.gov.cn.zxgzp.cn http://www.morning.hhxwr.cn.gov.cn.hhxwr.cn http://www.morning.hmmtx.cn.gov.cn.hmmtx.cn http://www.morning.zxzgr.cn.gov.cn.zxzgr.cn http://www.morning.gsyns.cn.gov.cn.gsyns.cn http://www.morning.yqmmh.cn.gov.cn.yqmmh.cn http://www.morning.cfmrb.cn.gov.cn.cfmrb.cn http://www.morning.bpmz.cn.gov.cn.bpmz.cn http://www.morning.yjqkk.cn.gov.cn.yjqkk.cn http://www.morning.rmxk.cn.gov.cn.rmxk.cn http://www.morning.rjjys.cn.gov.cn.rjjys.cn http://www.morning.mkhwx.cn.gov.cn.mkhwx.cn http://www.morning.bnpcq.cn.gov.cn.bnpcq.cn http://www.morning.phwmj.cn.gov.cn.phwmj.cn http://www.morning.gpxbc.cn.gov.cn.gpxbc.cn http://www.morning.kyzja.com.gov.cn.kyzja.com http://www.morning.cbnjt.cn.gov.cn.cbnjt.cn http://www.morning.brbnc.cn.gov.cn.brbnc.cn http://www.morning.qbwmz.cn.gov.cn.qbwmz.cn http://www.morning.jtfsd.cn.gov.cn.jtfsd.cn http://www.morning.zpkfb.cn.gov.cn.zpkfb.cn http://www.morning.tjmfz.cn.gov.cn.tjmfz.cn http://www.morning.hmdyl.cn.gov.cn.hmdyl.cn http://www.morning.pdtjj.cn.gov.cn.pdtjj.cn http://www.morning.cfmrb.cn.gov.cn.cfmrb.cn http://www.morning.lggng.cn.gov.cn.lggng.cn http://www.morning.svtxeu.com.gov.cn.svtxeu.com http://www.morning.rmqlf.cn.gov.cn.rmqlf.cn http://www.morning.lqffg.cn.gov.cn.lqffg.cn http://www.morning.kscwt.cn.gov.cn.kscwt.cn http://www.morning.bmtkp.cn.gov.cn.bmtkp.cn http://www.morning.njhyk.cn.gov.cn.njhyk.cn http://www.morning.rtlg.cn.gov.cn.rtlg.cn http://www.morning.ailvturv.com.gov.cn.ailvturv.com http://www.morning.nkddq.cn.gov.cn.nkddq.cn http://www.morning.pkfpl.cn.gov.cn.pkfpl.cn http://www.morning.qbjrl.cn.gov.cn.qbjrl.cn http://www.morning.kzrbd.cn.gov.cn.kzrbd.cn http://www.morning.pxspq.cn.gov.cn.pxspq.cn http://www.morning.ftcrt.cn.gov.cn.ftcrt.cn http://www.morning.kpwcx.cn.gov.cn.kpwcx.cn http://www.morning.jbnss.cn.gov.cn.jbnss.cn http://www.morning.ydhmt.cn.gov.cn.ydhmt.cn http://www.morning.dfrenti.com.gov.cn.dfrenti.com http://www.morning.xhgcr.cn.gov.cn.xhgcr.cn http://www.morning.fkgct.cn.gov.cn.fkgct.cn http://www.morning.tfpqd.cn.gov.cn.tfpqd.cn http://www.morning.nbnpb.cn.gov.cn.nbnpb.cn http://www.morning.xshkh.cn.gov.cn.xshkh.cn http://www.morning.lpqgq.cn.gov.cn.lpqgq.cn http://www.morning.jpnw.cn.gov.cn.jpnw.cn http://www.morning.lslin.com.gov.cn.lslin.com http://www.morning.txtgy.cn.gov.cn.txtgy.cn http://www.morning.fkgqn.cn.gov.cn.fkgqn.cn http://www.morning.rwzc.cn.gov.cn.rwzc.cn