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 @   自学Java笔记本  阅读(223)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
历史上的今天:
2023-09-12 阿里云内容审核增强版
点击右上角即可分享
微信分享提示