批量更新数据库
方案一
在循环中创建update语句。
<update id="updateBatchById">
<foreach collection="list" item="item" separator=";">
update
`t_student`
set
`name` = #{item.name},
`age` = #{item.age}
where
id = #{item.id}
</foreach>
</update>
这种方案的sql写起来比较方便,虽然他也只需要和数据库做一次连接,进行一次网络IO,但是数据库的服务器在执行sql的时候是需要根据“;”来区分然后一句一句执行的,所以在效率上还是不高的。
而且注意,默认情况下,数据库是不支持执行这样由";“号拼接的长串的,执行的时候会报错,提示说执行的SQL有语法错误。
我们需要通过在数据库连接URL中指定allowMultiQueries参数值为true告诉数据库以支持”;"号分隔的多条语句的执行。
spring.datasource.url=jdbc:mysql://localhost:3306/test?allowMultiQueries=true
方案二
借用case when来写一个update的sql语句。
update `t_student`
<trim prefix="set" suffixOverrides=",">
<trim prefix=" `name` = case " suffix=" end, ">
<foreach collection="list" item="item">
<if test="item.name != null">
when `id` = #{item.id} then #{item.name}
</if>
</foreach>
</trim>
<trim prefix=" `age` = case " suffix=" end, ">
<foreach collection="list" item="item">
<if test="item.age != null">
when `id` = #{item.id} then #{item.age}
</if>
</foreach>
</trim>
</trim>
where
`id` in
<foreach collection="list" item="item" open="(" close=")" separator=",">
#{item.id}
</foreach>
这种方案其实也不会不好理解,只是可读性差一点。它是通过把所有的对象遍历一遍然后获取指定的字段放进case语句中,很粗暴。这种方式编译出来就是一条sql语句,而不是第一种方案的n条语句的拼凑。
所以mybatis只要和mysql建立一次连接,同时在mysql服务器执行sql语句的时候只要执行一个in查询的sql语句。这个方案的效率明显比第一种方案要高。
测试
测试数据为六个字段的更新语句;记录数为251条。
方案一
方案二
两者相差100倍。