一.更新多条数据,每条数据都不一样

背景描述:通常如果需要一次更新多条数据有两个方式,(1)在业务代码中循环遍历逐条更新。(2)一次性更新所有数据(更准确的说是一条sql语句来更新所有数据,逐条更新的操作放到数据库端,在业务代码端展现的就是一次性更新所有数据)。两种方式各有利弊,下面将会对两种方式的利弊做简要分析,主要介绍第二种方式在mybatis中的实现。

1.逐条更新(java实现)

这种方式显然是最简单,也最不容易出错的,即便出错也只是影响到当条出错的数据,而且可以对每条数据都比较可控,更新失败或成功,从什么内容更新到什么内容,都可以在逻辑代码中获取。代码可能像下面这个样子:

updateBatch(List<MyData> datas){for(MyData data : datas){try{myDataDao.update(data);//更新一条数据,mybatis中如下面的xml文件的update}catch(Exception e){...//如果更新失败可以做一些其他的操作,比如说打印出错日志等}}
}//mybatis中update操作的实现
<update>update mydataset   ...where ...
</update>

这种方式最大的问题就是效率问题,逐条更新,每次都会连接数据库,然后更新,再释放连接资源(虽然通过连接池可以将频繁连接数据的效率大大提高,抗不住数据量大),这中损耗在数据量较大的时候便会体现出效率问题。这也是在满足业务需求的时候,通常会使用上述提到的第二种批量更新的实现(当然这种方式也有数据规模的限制,后面会提到)。

2.逐条更新(mybatis实现)

通过循环,依次执行多条update的sql

前提条件:

要实现批量更新,首先得设置mysql支持批量操作,在jdbc链接中需要附加&allowMultiQueries=true属性才行
例如:
jdbc:mysql://localhost:3306/dbname?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true
<update id="updateBatch"  parameterType="java.util.List">  <foreach collection="list" item="item" index="index" open="" close="" separator=";">update course<set>name=${item.name}</set>where id = ${item.id}</foreach>
</update>

一条记录update一次,性能比较差,容易造成阻塞。

3.sql批量更新(主力实现)

(1)、实际实践(传入的是List<Map<String, Object>>)

务必注意:一定要加where条件,里面的id为需要更新的数据的id;如果不加where条件,则会全部更新,但是需要更新且有数据的更新为传递的数据,没有数据的则更新为null,此时更新出错

<update id="updateChartParamByAccountAndChartid" parameterType="list">update followme_parameters<trim prefix="set" suffixOverrides=","><trim prefix="signal_source =case" suffix="end,"><foreach collection="list" item="item" index="index"><if test="item.signalSource!=null">when account=#{item.account} and chart_id=#{item.chartId}then #{item.signalSource}</if></foreach></trim><trim prefix="rate =case" suffix="end,"><foreach collection="list" item="item" index="index"><if test="item.rate!=null">when account=#{item.account} and chart_id=#{item.chartId}then #{item.rate}</if></foreach></trim></trim>where id in<foreach collection="list" item="item" index="index" separator="," open="(" close=")">#{item.id}</foreach></update>

另外文章的样板

<update id="updateBatch" parameterType="list">update course<trim prefix="set" suffixOverrides=","><trim prefix="peopleId =case" suffix="end,"><foreach collection="list" item="i" index="index"><if test="i.peopleId!=null">when id=#{i.id} then #{i.peopleId}</if></foreach></trim><trim prefix=" roadgridid =case" suffix="end,"><foreach collection="list" item="i" index="index"><if test="i.roadgridid!=null">when id=#{i.id} then #{i.roadgridid}</if></foreach></trim><trim prefix="type =case" suffix="end," ><foreach collection="list" item="i" index="index"><if test="i.type!=null">when id=#{i.id} then #{i.type}</if></foreach></trim><trim prefix="unitsid =case" suffix="end," ><foreach collection="list" item="i" index="index"><if test="i.unitsid!=null">when id=#{i.id} then #{i.unitsid}</if></foreach></trim></trim>where<foreach collection="list" separator="or" item="i" index="index" >id=#{i.id}</foreach>
</update>
---------------------
作者:junehappylove
来源:CSDN
原文:https://blog.csdn.net/junehappylove/article/details/82215674
版权声明:本文为博主原创文章,转载请附上博文链接!

(2)、下面逐步讲解

一条sql语句来批量更新所有数据,下面直接看一下在mybatis中通常是怎么写的(去掉mybatis语法就是原生的sql语句了,所有就没单独说sql是怎么写的)。

<update id="updateBatch" parameterType="java.util.List">update mydata_table set  status=<foreach collection="list" item="item" index="index" separator=" " open="case ID" close="end">when #{item.id} then #{item.status}</foreach>where id in<foreach collection="list" index="index" item="item" separator="," open="(" close=")">#{item.id,jdbcType=BIGINT}</foreach></update>

其中when...then...是sql中的"switch" 语法。这里借助mybatis的语法来拼凑成了批量更新的sql,上面的意思就是批量更新id在updateBatch参数所传递List中的数据的status字段。还可以使用实现同样的功能,代码如下:

<update id="updateBatch" parameterType="java.util.List">update mydata_table<trim prefix="set" suffixOverrides=","><trim prefix="status =case" suffix="end,"><foreach collection="list" item="item" index="index">when id=#{item.id} then #{item.status}</foreach></trim></trim>where id in<foreach collection="list" index="index" item="item" separator="," open="(" close=")">#{item.id,jdbcType=BIGINT}</foreach></update><trim>

属性说明

1.prefix,suffix 表示在trim标签包裹的部分的前面或者后面添加内容
2.如果同时有prefixOverrides,suffixOverrides 表示会用prefix,suffix覆盖Overrides中的内容。
3.如果只有prefixOverrides,suffixOverrides 表示删除开头的或结尾的xxxOverides指定的内容。

上述代码转化成sql如下:

update mydata_table set status = casewhen id = #{item.id} then #{item.status}//此处应该是<foreach>展开值...endwhere id in (...);

当然这是最简单的批量更新实现,有时候可能需要更新多个字段,那就需要将

<trim prefix="status =case" suffix="end,"><foreach collection="list" item="item" index="index">when id=#{item.id} then #{item.status}</foreach>
</trim>

复制拷贝多次,更改prefix和when...then...的内容即可.而如果当需要为某个字段设置默认值的时候可以使用else

<trim prefix="status =case" suffix="end,"><foreach collection="list" item="item" index="index">when id=#{item.id} then #{item.status}</foreach>else default_value
</trim>

还有更常见的情况就是需要对要更新的数据进行判断,只有符合条件的数据才能进行更新,这种情况可以这么做:

<trim prefix="status =case" suffix="end,"><foreach collection="list" item="item" index="index"><if test="item.status !=null and item.status != -1">when id=#{item.id} then #{item.status}</if></foreach>
</trim>

这样的话只有要更新的list中status != null && status != -1的数据才能进行status更新.其他的将使用默认值更新,而不会保持原数据不变.如果要保持原数据不变呢?即满足条件的更新,不满足条件的保持原数据不变,简单的来做就是再加一个,因为mybatis中没有if...else...语法,但可以通过多个实现同样的效果,如下:

<trim prefix="status =case" suffix="end,"><foreach collection="list" item="item" index="index"><if test="item.status !=null and item.status != -1">when id=#{item.id} then #{item.status}</if><if test="item.status == null or item.status == -1">when id=#{item.id} then mydata_table.status      //这里就是原数据</if></foreach>
</trim>

整体批量更新的写法如下:

<update id="updateBatch" parameterType="java.util.List">update mydata_table<trim prefix="set" suffixOverrides=","><trim prefix="status =case" suffix="end,"><foreach collection="list" item="item" index="index"><if test="item.status !=null and item.status != -1">when id=#{item.id} then #{item.status}</if><if test="item.status == null or item.status == -1">when id=#{item.id} then mydata_table.status//原数据</if></foreach></trim></trim>where id in<foreach collection="list" index="index" item="item" separator="," open="(" close=")">#{item.id,jdbcType=BIGINT}</foreach>
</update>

4.批量更新(单个字段,传参list),实际是sql批量更新的简化版本而已

(1)、单个字段方法1

<update id="updateByBatch" parameterType="java.util.List">update t_goodsset NODE_ID=<foreach collection="list" item="item" index="index"separator=" " open="case" close="end">when GOODS_ID=#{item.goodsId} then #{item.nodeId}</foreach>where GOODS_ID in<foreach collection="list" index="index" item="item"separator="," open="(" close=")">#{item.goodsId,jdbcType=BIGINT}</foreach></update>

(2)、单个字段方法2

<update id="updateByBatch" parameterType="java.util.List">UPDATEt_goodsSET NODE_ID = CASE<foreach collection="list" item="item" index="index">WHEN GOODS_ID = #{item.goodsId} THEN #{item.nodeId}</foreach>ENDWHERE GOODS_ID IN<foreach collection="list" index="index" item="item" open="(" separator="," close=")">#{item.goodsId}</foreach></update>

以上单字段更新实际执行:

UPDATE t_goods SET NODE_ID = CASE WHEN GOODS_ID = ? THEN ? END WHERE GOODS_ID IN ( ? )

5.sql批量更新(通过insert实现)

传入的是List<Map<String,Object>>

直接运行插入,如果有插入的数据转为更新该条数据

<insert id="updateChartParamByAccountAndChartid">insert into followme_parameters(account,chart_id,signal_source,rate)values<foreach collection="list" separator="," index="index" item="item">(#{item.account},#{item.chartId},#{item.signalSource},#{item.rate})</foreach>ON duplicate KEY UPDATEsignal_source=values(signal_source),rate=values(rate)
</insert>

二.更新多条数据,更新的内容一样.

1.传map/传String

NODE_ID从map中取出来,goodsIdList是字符串拼接好的(如下面的"1,2,5")

<update id="updateByBatchPrimaryKey" parameterType="java.util.Map">UPDATE t_goodsSET NODE_ID = #{nodeId}WHERE GOODS_ID IN (${goodsIdList})</update>

实际的sql

UPDATE t_goods SET NODE_ID = ? WHERE GOODS_ID IN (1,2,5);

2.传map/传list

NODE_ID从map中取出来,goodsIdList是用list拼接出来的

<update id="updateByBatchPrimaryKey" parameterType="java.util.Map">UPDATE t_goodsSET NODE_ID = #{nodeId}WHERE GOODS_ID IN <foreach collection="list" index="index" item="item" open="(" separator="," close=")">#{item.goodsId}</foreach>
</update>

实际的sql

UPDATE t_goods SET NODE_ID = ? WHERE GOODS_ID IN (1,2,5);

参考文章:

主力:Mybatis中进行批量更新(updateBatch)_Jin的专栏-CSDN博客_updatebatch
辅助:mybatis批量插入、批量更新和批量删除 - 简书

mybatis中批量更新相关推荐

  1. mybatis mysql 批量更新_mysql批量update更新,mybatis中批量更新操作

    在日常开发中,有时候会遇到批量更新操作,这时候最普通的写法就是循环遍历,然后一条一条地进行update操作.但是不管是在服务端进行遍历,还是在sql代码中进行遍历,都很耗费资源,而且性能比较差,容易造 ...

  2. php中update语句修改多个字段,Myabtis中批量更新update多字段

    在mybatis中批量更新多个字段 推荐使用如下操作: 方式1:在Dao层接口中: void updateBatch(@Param("list")List list); 在对应的m ...

  3. Mybatis之批量更新操作

    2019独角兽企业重金招聘Python工程师标准>>> Mybatis之批量更新操作 更新单条记录 1 UPDATE course SET name = 'course1' WHER ...

  4. Mybatis的批量更新 bug

    2019独角兽企业重金招聘Python工程师标准>>> Mybatis的批量更新 bug 博客分类: mybatis 异常 Mybatis的批量更新       Mybatis的批量 ...

  5. Mybatis之批量更新数据(批量update)

    前言 当我们使用mybatis的时候,可能经常会碰到一批数据的批量更新问题,因为如果一条数据一更新,那每一条数据就需要涉及到一次数据库的操作,包括网络IO以及磁盘IO,可想而知,这个效率是非常低下的. ...

  6. SpringBoot+Mybatis+Druid批量更新 multi-statement not allow异常

    SpringBoot+Mybatis+Druid批量更新 multi-statement not allow异常 参考文章: (1)SpringBoot+Mybatis+Druid批量更新 multi ...

  7. mybatis中显示更新数据成功 ,控制台显示成功,数据库数据却没有修改

    @mybatis中显示更新数据成功 ,控制台显示成功,数据库数据却没有修改 问题分析 查看控制台输出语句,控制台会打印更新方法的日志,显示一条更新语句成功等信息.但是查看数据库是没有任何变化的. 原因 ...

  8. 扩展tk.mybatis的批量更新的功能

    tk.mybatis没有带批量更新的功能,批量更新却是经常使用的,所以需要自己实现. 批量更新网上主要有2种方式:case when方式.foreach方式 但是foreachzhe这种方式效率非常低 ...

  9. mybatis执行批量更新batch update 的方法(oracle,mysql)

    oracle和mysql数据库的批量update在mybatis中配置不太一样: oracle数据库: <updateid="batchUpdate" parameterTy ...

最新文章

  1. Rhel6.0部署Oracle10g报错相关问题记录
  2. java socket抓取资源_Java 通过 Socket 的形式抓取网页内容
  3. 解决oracle ORA-01078,LRM-00109故障一例!
  4. .dat文件写入byte类型数组_文件字节流、文件字符流、缓冲字节流、缓冲字符流字节数组流、数据流、转换流、对象流...
  5. 使用python实现简单的爬虫
  6. 一个高质量的程序应具备哪些条件?_如何开好一个精品店?需要具备哪些条件?...
  7. 湖北大学计算机复试笔试题型,2016年湖北大学计算机与信息工程学院计算机组成原理复试笔试最后押题五套卷...
  8. C#基础概念面试题(更新中)
  9. 一键删除越狱环境方法教程,uncOvre4.0.2发布了
  10. 读书笔记004:王阳明语录
  11. 蒸汽流量计算软件_海口气体腰轮订制,涡街流量计脉冲,期待合作
  12. dz论坛php如何使用html模板,discuz自定义模板制作方法
  13. Keyshot渲染-关于导入提示:未检索到几何图形的解决方法。
  14. 基于微博平台的python爬虫数据采集,非常简单的小案例!
  15. 计算机专业英语容易挂科吗,大学英语专业容易挂科吗
  16. vite如何兼容低版本浏览器
  17. (非常实用)局部解剖学重点
  18. 自动驾驶打响新一轮“金元战”
  19. 论文的正确打开方式—如何细读一篇论文分享
  20. 第一章第十三题(代数:求解2 × 2线性方程组)(Algebra: solve 2 × 2 linear equations)

热门文章

  1. 高并发:线程、线程锁与线程池(精华),文中附上一个手写代码实现线程池视频(c/c++语言)
  2. 「Linux」C++后台开发面试总结(献给进击BAT的你)
  3. Vue混入 Vue Mixin
  4. route命令实例练习
  5. JavaScript 正则表达式 通俗解释 快速记忆
  6. win7 mac虚拟机linux,小白练习win7系统在虚拟机下装mac的具体方案
  7. 几乎刷完了力扣所有的树题,我发现了这些东西
  8. https://gist.github.com/nathanielove/40c1dcac777e64ceeb63d8296d263d6d
  9. Go:十大主流微服务框架
  10. linux shell遍历文件,Linux_shell脚本_遍历文件夹下所有文件