IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发工具 -> 使用case when then语句解决mybatis批量更新multi-statement not allow问题 -> 正文阅读

[开发工具]使用case when then语句解决mybatis批量更新multi-statement not allow问题

近期在开发过程中遇到了MyBatis批量更新的问题,控制台报错?multi-statement not allow,对应xml文件中的SQL如下:

? <update id="batchUpdateFwzymlAndQqfxx" parameterType="vo.pojo.PageData">
? ? ? ? <foreach collection="fwsqupdatelist" item="fwsq" separator=",">
? ? ? ? ? ? UPDATE sjgx_fwml_sqxx
? ? ? ? ? ? <set>
? ? ? ? ? ? ? ? <if test="fwsq.zdqqcs!=null and fwsq.zdqqcs!=''" >
? ? ? ? ? ? ? ? ? ? zdqqcs= #{fwsq.zdqqcs},
? ? ? ? ? ? ? ? </if>
? ? ? ? ? ? ? ? <if test="fwsq.ljqqcs!=null and fwsq.ljqqcs!=''" >
? ? ? ? ? ? ? ? ? ? ljqqcs= #{fwsq.ljqqcs},
? ? ? ? ? ? ? ? </if>
? ? ? ? ? ? ? ? gxsj=NOW()
? ? ? ? ? ? </set>
? ? ? ? ? ? WHERE id=#{fwsq.id}
? ? ? ? </foreach>
? ? </update>

执行后报错:
?org.springframework.jdbc.UncategorizedSQLException:?
### Error updating database. ?Cause: java.sql.SQLException: sql injection violation, multi-statement not allow :?
?? ??? ?UPDATE sjgx_fwml_sqxx?
?? ??? ?SET zdqqcs = ?,
?? ??? ?ljqqcs = ?,
?? ??? ?gxsj = NOW( )?
?? ??? ?WHERE
?? ??? ??? ?id =?;
?? ??? ??? ?
?? ??? ?UPDATE sjgx_fwml_sqxx?
?? ??? ?SET zdqqcs = ?,
?? ??? ?ljqqcs = ?,
?? ??? ?gxsj = NOW( )?
?? ??? ?WHERE
?? ??? ??? ?id =?;
?? ??? ??? ?
?? ??? ?UPDATE sjgx_fwml_sqxx?
?? ??? ?SET zdqqcs = ?,
?? ??? ?ljqqcs = ?,
?? ??? ?gxsj = NOW( )?
?? ??? ?WHERE
?? ??? ??? ?id =?;
?? ??? ??? ?
?? ??? ?UPDATE sjgx_fwml_sqxx?
?? ??? ?SET zdqqcs = ?,
?? ??? ?ljqqcs = ?,
?? ??? ?gxsj = NOW( )?
?? ??? ?WHERE
?? ??? ??? ?id =?;
?? ??? ??? ?
?? ??? ?UPDATE sjgx_fwml_sqxx?
?? ??? ?SET zdqqcs = ?,
?? ??? ?ljqqcs = ?,
?? ??? ?gxsj = NOW( )?
?? ??? ?WHERE
?? ??? ??? ?id =?;
?? ??? ??? ?
?? ??? ?UPDATE sjgx_fwml_sqxx?
?? ??? ?SET zdqqcs = ?,
?? ??? ?ljqqcs = ?,
?? ??? ?gxsj = NOW( )?
?? ??? ?WHERE
?? ??? ??? ?id =?

由控制台可见,其mybatis默认不支持多条语句的更新,需要设置相关属性。从社区里看到的解决方案大致思路为,先检查本地配置文件的url中是否配置了allowMultiQueries=true,如果配置了,但还是不起作用,再写一个配置类来解决。
查看本地的application.yml文件中的
? ? ?url: jdbc:mysql://127.0.0.1:3306/sk_sjz_sjgx_dev?allowMultiQueries=true&useUnicode=true&characterEncoding=utf-8&autoReconnect=true
已经加上了allowMultiQueries=true

再写一个配置类MyBatisConfig:

@Configuration
public class MyBatisConfig {

? ? @Bean
? ? @ConfigurationProperties(prefix = "spring.datasource")
? ? public DataSource dataSource(){
? ? ? ? List<Filter> filterList = null;
? ? ? ? DruidDataSource druidDataSource = new DruidDataSource();
? ? ? ? List<Filter> proxyFilters = druidDataSource.getProxyFilters();
? ? ? ? boolean isExit = false;
? ? ? ? for(Filter filter:proxyFilters){
? ? ? ? ? ? if(filter instanceof ?WallFilter){
? ? ? ? ? ? ? ? ((WallFilter) filter).setConfig(wallConfig());
? ? ? ? ? ? ? ? isExit = true;
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? if(!isExit){
? ? ? ? ? ? filterList= new ArrayList<>();
? ? ? ? ? ? filterList.add(wallFilter());
? ? ? ? ? ? druidDataSource.setProxyFilters(filterList);
? ? ? ? }
? ? ? ? return druidDataSource;

? ? }

? ? @Bean
? ? public WallFilter wallFilter(){
? ? ? ? WallFilter wallFilter = new WallFilter();
? ? ? ? wallFilter.setDbType(DbType.MYSQL.getDb());
? ? ? ? wallFilter.setConfig(wallConfig());
? ? ? ? return wallFilter;

? ? }

? ? @Bean
? ? public WallConfig wallConfig(){
? ? ? ? WallConfig config = new WallConfig();
? ? ? ? config.setMultiStatementAllow(true);//允许一次执行多条语句
? ? ? ? config.setNoneBaseStatementAllow(true); //允许非基本语句的其他语句
? ? ? ? return config;
? ? }

}

但还是不起作用,死活不好使,还报出了其他的错误:

Failed to obtain JDBC Connection: dbType not support : null,url null.........

这个若要讲清楚,必须了解MyBatis和DruidDataSource的底层实现,暂时还没有挖掘那么深,
就尝试了另一种批量更新的方式,即绕开了multi-statement not allow的问题,如下所示,

使用?case when?then 语句,可批量更新的操作:

<update id="batchUpdateFwzymlAndQqfxx" parameterType="vo.pojo.PageData">
? ? ? ? UPDATE sjgx_fwml_sqxx
? ? ? ? <trim prefix="set" suffixOverrides=",">

? ? ? ? ? ? <trim prefix="zdqqcs =case" suffix="end,">
? ? ? ? ? ? ? ? <foreach collection="updatelist" item="i" index="index">
? ? ? ? ? ? ? ? ? ? <if test="i.zdqqcs!=null">
? ? ? ? ? ? ? ? ? ? ? ? WHEN id=#{i.id} THEN #{i.zdqqcs}
? ? ? ? ? ? ? ? ? ? </if>
? ? ? ? ? ? ? ? </foreach>
? ? ? ? ? ? </trim>

? ? ? ? ? ? <trim prefix="ljqqcs =case" suffix="end,">
? ? ? ? ? ? ? ? <foreach collection="updatelist" item="i" index="index">
? ? ? ? ? ? ? ? ? ? <if test="i.ljqqcs!=null">
? ? ? ? ? ? ? ? ? ? ? ? WHEN id=#{i.id} THEN #{i.ljqqcs}
? ? ? ? ? ? ? ? ? ? </if>
? ? ? ? ? ? ? ? </foreach>
? ? ? ? ? ? </trim>

? ? ? ? ? ? <trim prefix="gxsj =case" suffix="end,">
? ? ? ? ? ? ? ? <foreach collection="updatelist" item="i" index="index">
? ? ? ? ? ? ? ? ? ? <if test="i.gxsj!=null">
? ? ? ? ? ? ? ? ? ? ? ? WHEN id=#{i.id} THEN #{i.gxsj}
? ? ? ? ? ? ? ? ? ? </if>
? ? ? ? ? ? ? ? </foreach>
? ? ? ? ? ? </trim>

? ? ? ? </trim>
? ? ? ? WHERE id IN
? ? ? ? <foreach collection="updatelist" item="i" open="(" close=")" separator=",">
? ? ? ? ? ? #{i.id}
? ? ? ? </foreach>
? ? </update>

控制台打印执行的sql为:
UPDATE sjgx_fwml_sqxx?
SET zdqqcs =
CASE
?? ?
?? ?WHEN id =? THEN
?? ???
?? ?WHEN id =? THEN
?? ???
?? ?WHEN id =? THEN
?? ???
?? ?WHEN id =? THEN
?? ???
?? ?WHEN id =? THEN
?? ???
?? ?WHEN id =? THEN
?? ???
?? ?END,
?? ?ljqqcs =
CASE
?? ??? ?
?? ??? ?WHEN id =? THEN
?? ??? ???
?? ??? ?WHEN id =? THEN
?? ??? ???
?? ??? ?WHEN id =? THEN
?? ??? ???
?? ??? ?WHEN id =? THEN
?? ??? ???
?? ??? ?WHEN id =? THEN
?? ??? ???
?? ??? ?WHEN id =? THEN
?? ??? ???
?? ?END,
?? ?gxsj =
CASE
?? ??? ?
?? ??? ?WHEN id =? THEN
?? ??? ???
?? ??? ?WHEN id =? THEN
?? ??? ???
?? ??? ?WHEN id =? THEN
?? ??? ???
?? ??? ?WHEN id =? THEN
?? ??? ???
?? ??? ?WHEN id =? THEN
?? ??? ???
?? ??? ?WHEN id =? THEN
?? ??? ???
?? ?END?
WHERE
id IN ( ?, ?, ?, ?, ?, ? )

其他博客中也将末尾处的where条件使用OR来匹配,如:
?WHERE
? ? ? ?id=?
? ? ?OR id=?
?? ? OR id=?
?? ? OR id=?
?? ? OR id=?
?? ? OR id=?

也是没有问题的,但是实际开发中不建议使用OR。
经测试,如果IN和OR所在列有索引或主键,OR和IN没有差别,随着数据量的增加,执行计划和执行时间几乎一样
如果IN和OR所在列没有索引和主键,随着数据量的增加,IN的性能不受影响,而OR的性能会下降的非常厉害。

? ? 以上方式实际并未解决multi-statement not allow的问题,只是绕开了这个问题,使用了另一种方式来解决,
特此记录,希望遇到或已解决此问题的同学予以指教,互相学习,互相探讨!

  开发工具 最新文章
Postman接口测试之Mock快速入门
ASCII码空格替换查表_最全ASCII码对照表0-2
如何使用 ssh 建立 socks 代理
Typora配合PicGo阿里云图床配置
SoapUI、Jmeter、Postman三种接口测试工具的
github用相对路径显示图片_GitHub 中 readm
Windows编译g2o及其g2o viewer
解决jupyter notebook无法连接/ jupyter连接
Git恢复到之前版本
VScode常用快捷键
上一篇文章      下一篇文章      查看所有文章
加:2021-11-10 12:36:19  更:2021-11-10 12:38:38 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 21:10:13-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码