版本:SpringBoot3.0.5 ShardingJDBC为5.2.1
假设我按照id进行分片存储,是没有问题的,但是查询的时候按照id匹配则报以下的错误,用除id以外的字段没问题
同理,我把分片字段改为age后,可以按照id查询,但是age也报这个错。这是什么情况
版本:SpringBoot3.0.5 ShardingJDBC为5.2.1
假设我按照id进行分片存储,是没有问题的,但是查询的时候按照id匹配则报以下的错误,用除id以外的字段没问题
同理,我把分片字段改为age后,可以按照id查询,但是age也报这个错。这是什么情况
经过一段源码研究,可能是设计者为了插件化考虑,在上面SPI提供的内置分片算法规则中,提供了一个ClassBasedShardingAlgorithm这个算法,其内部根据设置property,将自定义的算法通过反射创建出来。
下面是ClassBasedShardingAlgorithm算法部分源码
public final class ClassBasedShardingAlgorithm implements StandardShardingAlgorithm<Comparable<?>>, ComplexKeysShardingAlgorithm<Comparable<?>>, HintShardingAlgorithm<Comparable<?>> {
private static final String STRATEGY_KEY = "strategy";
private static final String ALGORITHM_CLASS_NAME_KEY = "algorithmClassName";
...
@Getter
@Setter
private Properties props = new Properties();
@Override
public void init() {
String strategyKey = props.getProperty(STRATEGY_KEY);
Preconditions.checkNotNull(strategyKey, "The props `%s` cannot be null when uses class based sharding strategy.", STRATEGY_KEY);
strategy = ClassBasedShardingAlgorithmStrategyType.valueOf(strategyKey.toUpperCase().trim());
algorithmClassName = props.getProperty(ALGORITHM_CLASS_NAME_KEY);#读取配置中的props ,取得自定义算法类
Preconditions.checkNotNull(algorithmClassName, "The props `%s` cannot be null when uses class based sharding strategy.", ALGORITHM_CLASS_NAME_KEY);
createAlgorithmInstance();
}
private void createAlgorithmInstance() {
switch (strategy) {
case STANDARD:
standardShardingAlgorithm = ClassBasedShardingAlgorithmFactory.newInstance(algorithmClassName, StandardShardingAlgorithm.class, props);#就在这里反射创建实例
break;
case COMPLEX:
complexKeysShardingAlgorithm = ClassBasedShardingAlgorithmFactory.newInstance(algorithmClassName, ComplexKeysShardingAlgorithm.class, props);
break;
case HINT:
hintShardingAlgorithm = ClassBasedShardingAlgorithmFactory.newInstance(algorithmClassName, HintShardingAlgorithm.class, props);
break;
default:
break;
}
}
@Override
public String doSharding(final Collection<String> availableTargetNames, final PreciseShardingValue<Comparable<?>> shardingValue) {
return standardShardingAlgorithm.doSharding(availableTargetNames, shardingValue); #实际上用反射出来的实例去计算
}
因此改一下配置
shardingsphere:
mode:
type: Memory
datasource:
names: master
master:
url: jdbc:mysql://192.168.1.55:3306/demoDb?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useAffectedRows=true&serverTimezone=GMT%2B8&useSSL=false&allowPublicKeyRetrieval=true
driver-class-name: com.mysql.cj.jdbc.Driver
username: demo
password: 12345678
type: com.alibaba.druid.pool.DruidDataSource
rules:
sharding:
binding-tables:
- "sys_user"
tables:
sys_user:
actual-data-nodes: master.sys_user_$->{0..1}
table-strategy:
standard:
sharding-column: id
sharding-algorithm-name: myShardingAlgorithm #引用算法名称
sharding-algorithms:
idModShardingAlgorithm:
props:
sharding-count: 2
type: MOD
myShardingAlgorithm: #新加的算法名称
props:
strategy: standard
# 自定义标准分配算法
algorithmClassName: com.kuizii.demo.core.config.IdModShardingAlgorithm
type: CLASS_BASED
自定义一个算法
public class IdModShardingAlgorithm implements StandardShardingAlgorithm<String> {
@Override
public String doSharding(Collection<String> collection, PreciseShardingValue<String> preciseShardingValue) {
for (String s : collection) {
Integer mod= Integer.parseInt( preciseShardingValue.getValue())%2;
if (s.endsWith( mod.toString())) {
return s;
}
continue;
}
return "sys_user";
}
@Override
public Collection<String> doSharding(Collection<String> collection, RangeShardingValue<String> rangeShardingValue) {
return null;
}
@Override
public void init() {
}
@Override
public String getType() {
return "MOD1";
}
}
经过改造,再运行,自定义的分片算法完成了!
相关源码查看我的
gitee项目