批量有比较常用的两种方法:
方式1 case when:
UPDATE t_eipo_stock_subscribe_order
SET publish_id =
CASE
WHEN id = 20253165 THEN
20190201
WHEN id = 20253166 THEN
20190201
WHEN id = 20253167 THEN
20190201
END,
capital_id =
CASE
WHEN id = 20253165 THEN
2020000079
WHEN id = 20253166 THEN
2020000079
WHEN id = 20253167 THEN
2020000079
END,
case when xxx = ?? then (伪代码) end
WHERE
id IN ( 20253165, 20253166, 20253167 )
对应的 mybatis 长这样
update id = id="updateBatch" parameterType="java.util.List">
<trim prefix="set" suffixOverrides=",">
<trim prefix="publish_id = case" suffix="end,">
<foreach collection="list" index="index" item="item">
when id = #{item.id,jdbcType=BIGINT} then #{item.publishId,jdbcType=BIGINT}
</foreach>
</trim>
<trim>
......
</trim>
</trim>
where id in
<foreach close=")" collection="list" item="item" open="(" separator=", ">
#{item.id,jdbcType=BIGINT}
</foreach>
方式2 foreach:
update table_name set publish_id = 20202024, operator_no = '101564453001421964', is_sub = 0, updated_at = '2022-1-3 17:21:42' where id = 1 ;
update table_name set publish_id = 20202024, operator_no = '101587017453312930', is_sub = 0, updated_at = '2022-1-3 17:21:42' where id = 2 ;
对应的 xml 长这样:
<update id="updateForch" parameterType="java.util.List" >
<foreach collection="list" item="item" index="index" open="" close="" separator=";">
update standard_relation
<set >
<if test="item.standardFromUuid != null" >
standard_from_uuid = #{item.standardFromUuid,jdbcType=VARCHAR},
</if>
<if test="item.standardToUuid != null" >
standard_to_uuid = #{item.standardToUuid,jdbcType=VARCHAR},
</if>
<if test="item.gmtModified != null" >
gmt_modified = #{item.gmtModified,jdbcType=TIMESTAMP},
</if>
</set>
where id = #{item.id,jdbcType=BIGINT}
</foreach>
</update>
测试方式,
从数据库里读取数据 然后 进行 update 操作 , 测试结果如下:
注意:
foreach 方式(方式2) 要想成功,需要在db链接url后面带一个参数 &allowMultiQueries=true
即: jdbc:mysql://localhost:3306/mysqlTest?characterEncoding=utf-8&allowMultiQueries=true
更新100条
更新500条
更新 1000条
更新 5000条
个人总结:
可见 foreach 方式并不一定比 case when 方式慢, 甚至数据量 大时反而更快.
为什么?
首先说明, 我测试用的表 总共 字段 大概有 40多个 , 所以不管用什么方式, mybatis 都要对 xml 种的标签进行解析. 问题就在这里了 ,
case when 方式 在解析 sql 语句时 每个字段 都要 for 对 传的 list 进行遍历 , 再解析程一条很长的 sql 交给 mysql 执行. 在数据量和字段上来时, 解析花费的时间 类似 笛卡尔乘积,
foreach 方式 它解析 sql 是 多条 以 “;” 结尾的 update 语句, 然后统一 提交给 mysql 执行 , 数据量大时 和 字段比较多时, 优势就体现出来了.
所以, 在 字段比较多的情况下 且数据量超过 1000 条 用 foreach 会比较快 , 字段比较少 用 case when 方式 ,
在数据量非常大时 , 批量操作时 最好 对 list 进行分批 进行 批量操作