引言
本次場景,公司透過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 中的條件需要符合哈。