shardingJdbc分表执行批量update不支持的解决方式

引言

本次场景,公司通过shardingjdbc 对mysql数据库进行分表,模糊匹配 按照createTime,每季度一张表的方式,精确匹配按照creatTime的方式。关于模糊匹配、精确匹配,自行在shardingjdbc官网查看,分表策略等。
由于是跟进createTime字段去作为分表的key,那么在执行 select、update、delete操作时,需要携带creatTime 字段。

案例

在执行过程中,导入的操作,基于easyexcel 我采用分批次的方式,批量去进行update操作,于是我的sql如下:

    <update id="batchUpdateTmsStatus">
        <foreach collection="tmsFollowBOList" item="item" separator=";">
            update bp_tms_logistics set expressStatus = #{item.expressStatus},userChange = 1,followStatus = #{item.status}
            where createTime = #{item.createTime,jdbcType=DATE}
            and expressNo = #{item.expressNo}
        </foreach>
    </update>

但是问题来了,通过日志发现,执行的sql脚本如下:

update xxxxx_2024_2
set expressStatus = ?,userChange = 1,followStatus = ?
where expressNo = ?
and  createTime = ?;
				 
update xxxxx
set expressStatus = ?,userChange = 1,followStatus = ?
where expressNo = ?
and  createTime = BETWEEN


::: [3, 2, SF2223211, 2024-09-10, 2, 1, SF05050505, 2024-09-09]

细心的可以发现,一个是xxxxx_2024_2 一个是xxxxx ,其实 xxxxx对于我们来说它只是虚拟表,并不存在,我们需要的是xxxxx_2024_2 的形式,而shardingjdbc 并没有 通过代理的方式,代理到正确的数据库表中,查看官网issues 发现,并不支持批量update的方式,也就是我上面的语句。
issues:https://github.com/apache/shardingsphere/issues/6665

解决

由于并不支持批量的操作,刚开始的想法是想直接for循环链接数据库得了,但是我觉得这样并不符合自己的方式,于是,想了想,或许采用 case - when 的方式是否可以实现呢,于是我修改sql如下:


    <update id="batchUpdateTmsStatus">
        update xxxxx
        <trim prefix="set" suffixOverrides=",">
            <trim prefix="expressStatus=case" suffix="end,">
                <foreach collection="tmsFollowBOList" item="item" index="index">
                    <if test="item.expressStatus != null">
                        when expressNo = #{item.expressNo} AND createTime = #{item.createTime,jdbcType=DATE} THEN #{item.expressStatus}
                    </if>
                </foreach>
            </trim>
            <trim prefix="userChange=case" suffix="end,">
                <foreach collection="tmsFollowBOList" item="item" index="index">
                    <if test="item.expressStatus != null">
                        when expressNo = #{item.expressNo} AND createTime = #{item.createTime,jdbcType=DATE} THEN 1
                    </if>
                </foreach>
            </trim>
            <trim prefix="followStatus=case" suffix="end,">
                <foreach collection="tmsFollowBOList" item="item" index="index">
                    <if test="item.status != null">
                        when expressNo = #{item.expressNo} AND createTime = #{item.createTime,jdbcType=DATE} THEN #{item.status}
                    </if>
                </foreach>
            </trim>
        </trim>
    </update>

里面的内容我就不解释了,采用这个方式可以解决批量update 的方式,其中 when 中的条件需要符合哈。

posted @ 2024-09-12 09:54  自学Java笔记本  阅读(532)  评论(0)    收藏  举报