zoukankan      html  css  js  c++  java
  • MyBatis批量更新

    逐条更新

      这种方式显然是最简单,也最不容易出错的,即便出错也只是影响到当条出错的数据,而且可以对每条数据都比较可控。

    代码

    1 updateBatch(List<MyData> datas){
    2     for(MyData data : datas){
    3         try{
    4             myDataDao.update(data);
    5         }
    6         catch(Exception e){
    7         }
    8     }
    9 }

    mybatis中update的实现

    1 <update>
    2     update mydata
    3     set ...
    4     where ...
    5 </update>

    单字段批量更新

      逐条更新最然简单,但是逐次连接断开数据库效率实在不高,因此诞生了批量更新的方法。

     1 <update id="updateBatch" parameterType="java.util.List">
     2     update mydata_table 
     3     set status=
     4     <foreach collection="list" item="item" index="index" separator=" " open="case ID" close="end">
     5         when #{item.id} then #{item.status}
     6     </foreach>
     7     where id in
     8     <foreach collection="list" index="index" item="item" separator="," open="(" close=")">
     9         #{item.id,jdbcType=BIGINT}
    10     </foreach>
    11 </update>

      其中when...then...是sql中的"switch" 语法。这里借助mybatis的<foreach>语法来拼凑成了批量更新的sql,上面的意思就是批量更新id在updateBatch参数所传递List中的数据的status字段。也可以使用<trim>实现同样的功能。

     1 <update id="updateBatch" parameterType="java.util.List">
     2     update mydata_table
     3     <trim prefix="set" suffixOverrides=",">
     4         <trim prefix="status =case" suffix="end,">
     5             <foreach collection="list" item="item" index="index">
     6                 when id=#{item.id} then #{item.status}
     7             </foreach>
     8         </trim>
     9     </trim>
    10     where id in
    11     <foreach collection="list" index="index" item="item" separator="," open="(" close=")">
    12         #{item.id,jdbcType=BIGINT}
    13     </foreach>
    14 </update>

      prefix,suffix 表示在trim标签包裹的部分的前面或者后面添加内容,如果同时有prefixOverrides,suffixOverrides 表示会用prefix,suffix覆盖Overrides中的内容。 

    如果只有prefixOverrides,suffixOverrides 表示删除开头的或结尾的xxxOverides指定的内容。

     上述代码转化成sql如下:

    1 update mydata_table 
    2 set status = 
    3 case
    4     when id = #{item.id} then #{item.status}
    5     ...
    6 end
    7 where id in (...);

    带条件多字段批量更新

     1 <update id="updateBatch" parameterType="java.util.List">
     2     update sys_user
     3     <trim prefix="set" suffixOverrides=",">
     4         <trim prefix="userName = case" suffix="end,">
     5             <foreach collection="list" item="item" index="index">
     6                 <if test="item.userName != null">
     7                     when userId=#{item.userId} then #{item.userName}
     8                 </if>
     9             </foreach>
    10         </trim>
    11         <trim prefix="userCode = case" suffix="end,">
    12             <foreach collection="list" item="item" index="index">
    13                 <if test="item.userCode != null or item.userName == null">
    14                     when userId=#{item.userId} then #{item.userCode}
    15                 </if>
    16             </foreach>
    17         </trim>
    18     </trim>
    19     where userId in
    20     <foreach collection="list" index="index" item="item" separator="," open="(" close=")">
    21         #{item.userId}
    22     </foreach>
    23 </update>

      这种批量跟心数据库的方式可以在一次数据库连接中更新所有数据,避免了频繁数据库建立和断开连接的开销,可以很大程度的提高数据更新效率。但是这样的问题是如果这个过程中更新出错,将很难知道具体是哪个数据出错,如果使用数据自身的事务保证,那么一旦出错,所有的更新将自动回滚。而且通常这种方式也更容易出错。因此通常的使用的方案是进行折中,也就是一次批量更新一部分(分页进行更新,比如说一共有1000条数据,一次更新100条)。这样可以分担出错的概率,也更容易定位到出错的位置。 当然如果数据量确实很大的时候,这种批量更新也一样会导致更新效率低下(比如说一次更新100条,那如果10亿条数据呢,一样要批量更新1000万次,建立和断开1000万次数据库,这个效率是无法承受的)。这时候也许只能考虑其他方案了,比如引入缓存机制等。

  • 相关阅读:
    052-233(新增70题2018)
    052-232(新增70题2018)
    052-231(新增70题2018)
    052-230(新增70题2018)
    052-229(新增70题2018)
    052-228(新增70题2018)
    052-227(新增70题2018)
    052-226(新增70题2018)
    052-225(新增70题2018)
    进制之间的那点事(二进制、八进制、十进制、十六进制)
  • 原文地址:https://www.cnblogs.com/guanghe/p/10437404.html
Copyright © 2011-2022 走看看