一、简介
在程序开发过程中,往往会遇到需要更新一批数据(批量更新)的情况,这种情况通常有两种方法进行解决。这两种方法各有优点与缺点,这就需要我们根据实际业务需要进行取舍。
二、操作
1、逐条更新(不推荐)
直接在程序上使用循环对数据库进行数据更新,使用这样的方式是最简单、最不容易出错的方式。也不会出现因为一条数据更新失败,而导致全部数据更新失败。
执行Java代码如下:
updateBatch(List<Demo> demos){
for(User user : users){
try{
demoMapper.update(user);
} catch(Exception e){
//如果更新失败可以做一些其他的操作,比如说打印出错日志等
logger.error("更新数据失败,失败数据为:{},异常信息为:{}", user, e.getMessage())
}
}
}
执行SQL语句如下:
update
user
set
mark = #{mark}
where
id = #{id}
虽然这样做简单省事,但是会产生一个较大的问题,那就是执行效率问题。由于是循环执行,数据库连接连接释放,再连接再释放,知道循环结束。大量的占用数据库连接池内连接,从而影响执行效率。
2、批量更新(推荐)
批量更新是使用SQL的批量更新方式进行,使用 CASE ... WHEN ... THAN...
的语法进行批量操作。我们借助 MyBatis
的 <foreach>
语法进行SQL拼接成可以批量更新的SQL语句 。
我们以将表中特定id数据的mark字段修改为制定值为例。
Java程序中Dao层代码写法如下:
public intupdateBatch(List<User> idList);
MyBatis的xml文件中书写方法如下:
<update id="updateBatch" parameterType="java.util.List">
update
demo
set
mark = CASE
<foreach collection="list" item="m" index="index">
<if test="m.mark!= null and m.mark!= ''">
when id = #{m.id} then #{m.mark}
</if>
</foreach>
END
WHERE
id in
<foreach collection="list" item="m" index="index" open="(" separator="," close=")">
#{m.id}
</foreach>
</update>
按照如上方式,执行SQL过程中就会一次性将数据批量更新入数据库中。
之所以可以使用 CASE ... WHEN
方式进行批量更新,主要是因为 in
关键字的特性。 使用 in
关键字作为条件进行读操作或者是写操作时,实际相当于多个 or
条件进行叠加。
使用 in
关键字的查询语句
SELECT id FROM user WHERE id in (1, 2, 3);
与如下使用 or
关键字的查询SQL等价
SELECT id FROM user WHERE id = 1 or id = 2 or id = 3
假设 in
关键字中有 m 个条件,实际进行执行过程时,就会执行 m 次,最后将执行结果合并到一起(读写操作都是如此)。