sharding sphere 分多张表不支持 xml 中的批量更新以及解决方式

现象

在同一个库中,将一张表分成多张,在xml中使用如下的语法:

<foreach collection="params" item="item" separator=";">
    update table_hello set column_hello = #{item.itemHello} where sharding_key = #{item.shardingKey}
</foreach>

PreciseShardingAlgorithm:

public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<String> shardingValue) {
        Long value = doSharding(shardingValue.getValue());
        for (String each : availableTargetNames) {
            if (each.endsWith(value % 16 + "")) {
                return each;
            }
        }
        return null;
}

根据主观臆想,生成每条sql的时候,sharding sphere都会帮我们替换一下表名,但是跑起来的时候将会直接出错,报出表名不存在的错误,

根据log打印出来的真实sql来看,例如有三条更新语句,只有第一条被替换成了真实的表名,其他的没有被替换,

这点经过验证,官方给出的回复是,因为虽然有多条语句,但是这只是同一次sql请求,因此他们不支持这么做,只会将第一个表名替换掉,

这么做我想可能是有一定的考量的,比如路由的键值有很多,可能会同一次请求有很多不同的路由,甚至如果分库了可能会路由到不同的库中,所以官方限制了这个使用。

官方回复:https://github.com/apache/shardingsphere/issues/6665

解决方式

前提:保证多条update语句的路由键值是同一个,保证路由的统一性,

在循环sql中,根据路由规则动态生成表名,这需要mybatis中调用生成路由key的类和方法:

<foreach collection="params" item="item" separator=";">
    update table_hello set column_hello = #{item.itemHello_${@java包路径.类名@生成路由key方法(item.key参数)}} where sharding_key = #{item.shardingKey}
</foreach>

我们利用xml中可以动态生成表名的方式,来解决这个问题,但是最好一定要保证item.key参数是同一个,例如更新一个订单的明细,因为一个订单号的明细的路由规则可能是根据订单号来路由的。

后记

有个很好玩的事情,当时一个同事和我用一样的写法,就是上文现象里的写法,他的是可以的,但是我的不行,

就觉得很诡异,难道官方偷偷的支持了? 后来发现并不是,我们开发的是不同的模块,

因为他用的是分库,没有分表,多条update语句只需要路由到其中的库中,直接更新他库中的一张表就行了,

所以表名不需要被sharding sphere替换,用原始的就好,

但是我的因为分表了, 原始表名是需要被替换的,因此出现了感觉上这么一个奇怪的问题。

上一篇:2018.11.24 spoj New Distinct Substrings(后缀数组)


下一篇:分库分表——Sharding-Sphere