java.sql.BatchUpdateException: Communications link failure

java.sql.BatchUpdateException: Communications link failure

 

由于业务需求,需要使用mybatis对一个表进行批量update操作,mybatis的Mapper文件大致如下:

<update id="batchUpdate" parameterType="java.util.List">
        update user
        <trim prefix="set" suffixOverrides=",">
            <trim prefix="name =case" suffix="end,">
                <foreach collection="list" item="item" index="index">
                    <if test="item.name !=null and item.name != ''">
                        when ID=#{item.id} then #{item.name}
                    </if>
                    <if test="item.name ==null or item.name == ''">
                        when ID=#{item.id} then user.name
                    </if>
                </foreach>
            </trim>
            <trim prefix="birthday=case" suffix="end,">
                <foreach collection="list" item="item" index="index">
                    <if test="item.birthday !=null">
                        when ID=#{item.id} then #{item.birthday}
                    </if>
                    <if test="item.birthday ==null">
                        when ID=#{item.id} then user.BIRTHDAY
                    </if>
                </foreach>
            </trim>
        </trim>
        ,UPDATE_TIME = NOW(),UPDATOR=#{item.updator}
        where ID in
        <foreach collection="list" index="index" item="item" separator="," open="(" close=")">
            #{item.id,jdbcType=VARCHAR}
        </foreach>
    </update>

当数据量小的时候,这段程序运行没有问题,但是当一次更新超过5000条时(根据mysql的配置决定)就会抛出如下异常:

java.sqlBatchUpdateException.Communicationslinkfailure 
The last packet successfully received from the server was 10 milliseconds ago.
The last packet sent successfully to the server was 10 milliseconds ago:SQL[];

 

想象一下如果用上述批量更新一次性更新5000条数据的化,整个update语句是非常长的,因为它采用的是如下形式:

 

update user set name= case when .. then ..
                           when..then 
			   ......
			   end,
	     birthday= case when .. then ..
                           when..then 
			   ......
			   end
	     where id in(..,..,.......) 

后来经过实验一次更新1000条不会报错,最后为保障程序运行最后采用分批提交的方式来完成此项功能.将原有需更新的list拆分,分批提交更新.

//update分批提交,每次最多500条.防止数据库报
int batch = (list.size() < 500) ? 1 : ((list.size() / 500) + (((list.size() % 500) == 0) ? 0 : 1));
logger.info("共更新:" + list.size() + "条记录,分" + batch + "批提交");
List<List<Dweller>> splitList = ListUtil.split(list, batch);
for (List<User> tempList : splitList) {
        userMapper.batchUpdate(tempList);
}

//list分割函数
public static <T> List<List<T>> split(List<T> source, int n) {
    List<List<T>> result = new ArrayList<List<T>>();
    //(先计算出余数)
    int remaider = source.size() % n;
    //然后是商
    int number = source.size() / n;
    //偏移量
    int offset = 0;
    for (int i = 0; i < n; i++) {
        List<T> value = null;
        if (remaider > 0) {
            value = source.subList(i * number + offset, (i + 1) * number + offset + 1);
            remaider--;
            offset++;
        } else {
            value = source.subList(i * number + offset, (i + 1) * number + offset);
        }
        result.add(value);
    }
    return result;
}

 

 

 

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值