<updateid="updateBatch"parameterType="java.util.List"> <foreachcollection="list"item="item"index="index"open=""close=""separator=";"> update course <set> name=${item.name} </set> where id = ${item.id} </foreach> </update>
一条记录 update 一次,性能比较差,容易造成阻塞。
sql 批量更新(主力实现)
实际实践(传入的是 List
务必注意:一定要加 where 条件,里面的 id 为需要更新的数据的 id;如果不加 where 条件,则会全部更新,但是需要更新且有数据的更新为传递的数据,没有数据的则更新为 null,此时更新出错
<updateid="updateChartParamByAccountAndChartid"parameterType="list"> update followme_parameters <trimprefix="set"suffixOverrides=","> <trimprefix="signal_source =case"suffix="end,"> <foreachcollection="list"item="item"index="index"> <iftest="item.signalSource!=null"> when account=#{item.account} and chart_id=#{item.chartId} then #{item.signalSource} </if> </foreach> </trim> <trimprefix="rate =case"suffix="end,"> <foreachcollection="list"item="item"index="index"> <iftest="item.rate!=null"> when account=#{item.account} and chart_id=#{item.chartId} then #{item.rate} </if> </foreach> </trim> </trim> where id in <foreachcollection="list"item="item"index="index"separator=","open="("close=")"> #{item.id} </foreach> </update>
另外文章的样板
<updateid="updateBatch"parameterType="list"> update course <trimprefix="set"suffixOverrides=","> <trimprefix="peopleId =case"suffix="end,"> <foreachcollection="list"item="i"index="index"> <iftest="i.peopleId!=null"> when id=#{i.id} then #{i.peopleId} </if> </foreach> </trim> <trimprefix=" roadgridid =case"suffix="end,"> <foreachcollection="list"item="i"index="index"> <iftest="i.roadgridid!=null"> when id=#{i.id} then #{i.roadgridid} </if> </foreach> </trim> <trimprefix="type =case"suffix="end," > <foreachcollection="list"item="i"index="index"> <iftest="i.type!=null"> when id=#{i.id} then #{i.type} </if> </foreach> </trim> <trimprefix="unitsid =case"suffix="end," > <foreachcollection="list"item="i"index="index"> <iftest="i.unitsid!=null"> when id=#{i.id} then #{i.unitsid} </if> </foreach> </trim> </trim> where <foreachcollection="list"separator="or"item="i"index="index" > id=#{i.id} </foreach> </update>
<updateid="updateBatch"parameterType="java.util.List"> update mydata_table set status= <foreachcollection="list"item="item"index="index" separator=" "open="case ID"close="end"> when #{item.id} then #{item.status} </foreach> where id in <foreachcollection="list"index="index"item="item" separator=","open="("close=")"> #{item.id,jdbcType=BIGINT} </foreach> </update>
其中 when…then…是 sql 中的”switch” 语法。这里借助 mybatis 的语法来拼凑成了批量更新的 sql,上面的意思就是批量更新 id 在 updateBatch 参数所传递 List 中的数据的 status 字段。还可以使用实现同样的功能,代码如下:
<updateid="updateBatch"parameterType="java.util.List"> update mydata_table <trimprefix="set"suffixOverrides=","> <trimprefix="status =case"suffix="end,"> <foreachcollection="list"item="item"index="index"> when id=#{item.id} then #{item.status} </foreach> </trim> </trim> where id in <foreachcollection="list"index="index"item="item"separator=","open="("close=")"> #{item.id,jdbcType=BIGINT} </foreach> </update>
<trimprefix="status =case"suffix="end,"> <foreachcollection="list"item="item"index="index"> <iftest="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…语法,但可以通过多个实现同样的效果,如下:
<trimprefix="status =case"suffix="end,"> <foreachcollection="list"item="item"index="index"> <iftest="item.status !=null and item.status != -1"> when id=#{item.id} then #{item.status} </if> <iftest="item.status == null or item.status == -1"> when id=#{item.id} then mydata_table.status //这里就是原数据 </if> </foreach> </trim>
整体批量更新的写法如下:
<updateid="updateBatch"parameterType="java.util.List"> update mydata_table <trimprefix="set"suffixOverrides=","> <trimprefix="status =case"suffix="end,"> <foreachcollection="list"item="item"index="index"> <iftest="item.status !=null and item.status != -1"> when id=#{item.id} then #{item.status} </if> <iftest="item.status == null or item.status == -1"> when id=#{item.id} then mydata_table.status//原数据 </if> </foreach> </trim> </trim> where id in <foreachcollection="list"index="index"item="item"separator=","open="("close=")"> #{item.id,jdbcType=BIGINT} </foreach> </update>
批量更新(单个字段,传参 list),实际是 sql 批量更新的简化版本而已
单个字段方法 1
<updateid="updateByBatch"parameterType="java.util.List"> update t_goods set NODE_ID= <foreachcollection="list"item="item"index="index" separator=" "open="case"close="end"> when GOODS_ID=#{item.goodsId} then #{item.nodeId} </foreach> where GOODS_ID in <foreachcollection="list"index="index"item="item" separator=","open="("close=")"> #{item.goodsId,jdbcType=BIGINT} </foreach> </update>
单个字段方法 2
<updateid="updateByBatch"parameterType="java.util.List"> UPDATE t_goods SET NODE_ID = CASE <foreachcollection="list"item="item"index="index"> WHEN GOODS_ID = #{item.goodsId} THEN #{item.nodeId} </foreach> END WHERE GOODS_ID IN <foreachcollection="list"index="index"item="item"open="("separator=","close=")"> #{item.goodsId} </foreach> </update>
以上单字段更新实际执行:
UPDATE t_goods SET NODE_ID =CASEWHEN GOODS_ID = ? THEN ? ENDWHERE GOODS_ID IN ( ? )
sql 批量更新(通过 insert 实现)
传入的是 List
<insertid="updateChartParamByAccountAndChartid"> insert into followme_parameters (account,chart_id,signal_source,rate) values <foreachcollection="list"separator=","index="index"item="item"> (#{item.account},#{item.chartId},#{item.signalSource},#{item.rate}) </foreach> ON duplicate KEY UPDATE signal_source=values(signal_source),rate=values(rate) </insert>
<updateid="updateByBatchPrimaryKey"parameterType="java.util.Map"> UPDATE t_goods SET NODE_ID = #{nodeId} WHERE GOODS_ID IN (${goodsIdList}) </update>
实际的 sql
UPDATE t_goods SET NODE_ID = ? WHERE GOODS_ID IN (1,2,5);
传 map/传 list
NODE_ID 从 map 中取出来,goodsIdList 是用 list 拼接出来的
<updateid="updateByBatchPrimaryKey"parameterType="java.util.Map"> UPDATE t_goods SET NODE_ID = #{nodeId} WHERE GOODS_ID IN <foreachcollection="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);