配置手册 :: ShardingSphere
https://shardingsphere.apache.org/document/legacy/4.x/document/cn/manual/sharding-jdbc/configuration/
shardingsphere官方文档。今天我们用shardingJDBC做按天分表
依赖
<!-- 分表 --> <dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>sharding-jdbc-spring-boot-starter</artifactId> <version>4.1.1</version> </dependency>
配置
根据配置手册一点点配置连接数据库,然后做入库规则。
// 配置数据源以及数据库连接池
//因为我使用得是HikariDataSource,所以url使用的是spring.shardingsphere.datasource.master.jdbc-url,其他的我还没试过
//type是一定要配置的
spring.shardingsphere.datasource.names=master
spring.shardingsphere.datasource.master.jdbc-url=jdbc:mysql://localhost:3306/数据库?useSSL=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
spring.shardingsphere.datasource.master.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.master.username=账号
spring.shardingsphere.datasource.master.password=密码
spring.shardingsphere.datasource.master.type=com.zaxxer.hikari.HikariDataSource
//数据库节点,入哪几个数据库,这里我们暂且这么写,因为后边我们需要动态更新
spring.shardingsphere.sharding.tables.表名.actual-data-nodes=master.表名$->{20220604..20220605}
//根据哪个字段判断入表
spring.shardingsphere.sharding.tables.表名.table-strategy.standard.sharding-column=create_time
//指定分表算法策略的类(自定义的类)
spring.shardingsphere.sharding.tables.表名.table-strategy.standard.precise-algorithm-class-name=com.lt.config.DateAlgorithm
// 主键
spring.shardingsphere.sharding.tables.表名.key-generator.column=id
// 主键策略
spring.shardingsphere.sharding.tables.表名.key-generator.type=SNOWFLAKE
// 表名不加后缀
spring.shardingsphere.sharding.binding-tables=表名
注意上边我们自定义了分表算法策略,也就是这个配置
spring.shardingsphere.sharding.tables.表名.table-strategy.standard.precise-algorithm-class-name=com.lt.config.DateAlgorithm
这个类主要是为了让我们自定义分表策略。但是前提是,我们需要拿到全部的表,才能用策略去入表。现在我们的配置是
spring.shardingsphere.sharding.tables.表名.actual-data-nodes=master.表名$->{20220604..20220605}
这里只配置了两个表,那肯定是远远不够的。那么,现在我们就要考虑如何去拿到全部的表。我的做法是:新增一个表,去管理分表。类似于
把表名都交给mangage去管理。当我们查询mangage表的时候就可以看到全部表名。(建表是需要自己的定时任务去建表)
接下来我们就要把拿到的表名全部注入到框架扫描类的属性节点(SpringBootShardingRuleConfigurationProperties)里。
private final SpringBootShardingRuleConfigurationProperties shardingRuleConfigurationProperties;
private final MangageMapper mangageMapper;
public static SpringBootShardingRuleConfigurationProperties cloneRuleConfigurationProperties = null;
@PostConstruct
public void initDataNodes(){
// 检查今天明天的表是否存在(自定义方法,自己想怎么检查怎么检查)
checkTableExist();
// 加载mangage表获取都有哪些天的表
List<Mangage> list = mangage.selectList(null);
// 拿到所有后缀。Suffix是Mangage表的一个属性
List<Integer> suffixList = list.stream().map(Mangage::getSuffix).collect(Collectors.toList());
// 动态注入扩展节点到shardingRuleConfigurationProperties
Map<String, YamlTableRuleConfiguration> tables = shardingRuleConfigurationProperties.getTables();
YamlTableRuleConfiguration table = tables.get("表名");
// 组装属性
StringBuilder stringBuilder = new StringBuilder("master.表名$->{");
for (int i = 0; i < suffixList.size(); i++) {
stringBuilder.append(suffixList.get(i));
if (i==suffixList.size()-1){
stringBuilder.append("}");
}else {
stringBuilder.append(",");
}
}
// 事例master.表名$->{20220604,20220605,20220606}
table.setActualDataNodes(stringBuilder.toString());
// cloneRuleConfigurationProperties供全局查看使用
cloneRuleConfigurationProperties = shardingRuleConfigurationProperties;
}
这样就有了所有表名。然后我们配置我们自定义的路由规则。target就是路由的表的全名
public class DateAlgorithm implements PreciseShardingAlgorithm {
@Override
// 简单说就是拿到所有分表,然后根据preciseShardingValue去自定义匹配想入哪个表
public String doSharding(Collection collection, PreciseShardingValue preciseShardingValue) {
// 获取全部表路由
ArrayList<String> list = new ArrayList<>();
Map<String, YamlTableRuleConfiguration> tables =
cloneRuleConfigurationProperties.getTables();
YamlTableRuleConfiguration table = tables.get("表名");
String logicTable = table.getLogicTable();
String nodes = table.getActualDataNodes();
int il = nodes.lastIndexOf("{");
String substringNodes = nodes.substring(il+1, nodes.length() - 1);
String[] splitNodes = substringNodes.split(",");
for (int i = 0; i < splitNodes.length; i++) {
list.add(logicTable+splitNodes[i]);
}
// 匹配路由,返回路由表表名
String suffix = null;
if (preciseShardingValue.getValue() instanceof Date){
Date value =(Date) preciseShardingValue.getValue();
suffix = new SimpleDateFormat("yyyyMMdd").format(value);
}else {
String value =(String) preciseShardingValue.getValue();
suffix = value.split("T")[0].replace("-", "");
}
String target = null;
for (int i = 0; i < list.size(); i++) {
if (list.get(i).contains(suffix)){
target = list.get(i);
break;
}
}
return target;
}
}
最后,之前我们需要拿到全部的表。但是表每天都有新的创建,所以我们在创建表之后立即去更新获取我们全部的表即可。
以上仅为我个人使用的理解。用法或许不规范,请指出。