逐条更新
这种方式显然是最简单,也最不容易出错的,即便出错也只是影响到当条出错的数据,而且可以对每条数据都比较可控。
代码
1 updateBatch(Listdatas){2 for(MyData data : datas){3 try{4 myDataDao.update(data);5 }6 catch(Exception e){7 }8 }9 }
mybatis中update的实现
12 update mydata3 set ...4 where ...5
单字段批量更新
逐条更新最然简单,但是逐次连接断开数据库效率实在不高,因此诞生了批量更新的方法。
12 update mydata_table 3 set status= 4 5 when #{item.id} then #{item.status} 6 7 where id in 89 #{item.id,jdbcType=BIGINT}10 11
其中when...then...是sql中的"switch" 语法。这里借助mybatis的<foreach>语法来拼凑成了批量更新的sql,上面的意思就是批量更新id在updateBatch参数所传递List中的数据的status字段。也可以使用<trim>实现同样的功能。
12 update mydata_table 3 4 10 where id in115 96 when id=#{item.id} then #{item.status} 7 812 #{item.id,jdbcType=BIGINT}13 14
prefix,suffix 表示在trim标签包裹的部分的前面或者后面添加内容,如果同时有prefixOverrides,suffixOverrides 表示会用prefix,suffix覆盖Overrides中的内容。
如果只有prefixOverrides,suffixOverrides 表示删除开头的或结尾的xxxOverides指定的内容。
上述代码转化成sql如下:
1 update mydata_table 2 set status = 3 case4 when id = #{item.id} then #{item.status}5 ...6 end7 where id in (...);
带条件多字段批量更新
12 update sys_user 3 4 19 where userId in205 116 107 when userId=#{item.userId} then #{item.userName} 8 912 1813 1714 when userId=#{item.userId} then #{item.userCode}15 1621 #{item.userId}22 23
这种批量跟心数据库的方式可以在一次数据库连接中更新所有数据,避免了频繁数据库建立和断开连接的开销,可以很大程度的提高数据更新效率。但是这样的问题是如果这个过程中更新出错,将很难知道具体是哪个数据出错,如果使用数据自身的事务保证,那么一旦出错,所有的更新将自动回滚。而且通常这种方式也更容易出错。因此通常的使用的方案是进行折中,也就是一次批量更新一部分(分页进行更新,比如说一共有1000条数据,一次更新100条)。这样可以分担出错的概率,也更容易定位到出错的位置。 当然如果数据量确实很大的时候,这种批量更新也一样会导致更新效率低下(比如说一次更新100条,那如果10亿条数据呢,一样要批量更新1000万次,建立和断开1000万次数据库,这个效率是无法承受的)。这时候也许只能考虑其他方案了,比如引入缓存机制等。