前言
-
本项目分表方案是按照时间字段按日分表 其他分表方案也可参考本文档实现自动建表
-
需要提前准备待分表的主表写入数据库
-
优势:
可以实现自动建表 且不需要配置 SQL
范围分表查询时自动排除不存在的表
配置
主要依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.7</version>
</dependency>
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>4.0.1</version>
</dependency>
import com.**.**.dao.CommonMapper;
import com.**.**.domain.db.CreateTableSql;
import lombok.extern.slf4j.Slf4j;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.RangeShardingAlgorithm;
import java.util.HashSet;
import java.util.List;
@Slf4j
public abstract class ShardingAlgorithmTool<T extends Comparable<?>> implements PreciseShardingAlgorithm<T>, RangeShardingAlgorithm<T> {
private static CommonMapper commonMapper;
private static final HashSet<String> tableNameCache = new HashSet<>();
public static void setCommonMapper(CommonMapper commonMapper) {
ShardingAlgorithmTool.commonMapper = commonMapper;
}
public String shardingTablesCheckAndCreatAndReturn(String logicTableName, String resultTableName) {
synchronized (logicTableName.intern()) {
if (shardingTablesExistsCheck(resultTableName)) {
return resultTableName;
}
CreateTableSql createTableSql = commonMapper.selectTableCreateSql(logicTableName);
String sql = createTableSql.getCreateTable();
sql = sql.replace("CREATE TABLE", "CREATE TABLE IF NOT EXISTS");
sql = sql.replace(logicTableName, resultTableName);
commonMapper.executeSql(sql);
tableNameCache.add(resultTableName);
}
return resultTableName;
}
public boolean shardingTablesExistsCheck(String resultTableName) {
return tableNameCache.contains(resultTableName);
}
public static void tableNameCacheReload(String schemaName) {
List<String> tableNameList = commonMapper.getAllTableNameBySchema(schemaName);
ShardingAlgorithmTool.tableNameCache.clear();
ShardingAlgorithmTool.tableNameCache.addAll(tableNameList);
}
}
分表实现类 DateShardingAlgorithm
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.google.common.collect.Range;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingValue;
import org.apache.shardingsphere.api.sharding.standard.RangeShardingValue;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
public class DateShardingAlgorithm extends ShardingAlgorithmTool<Date> {
@Override
public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Date> preciseShardingValue) {
return shardingTablesCheckAndCreatAndReturn(preciseShardingValue.getLogicTableName(), preciseShardingValue.getLogicTableName() + DateUtil.format(preciseShardingValue.getValue(), "_yyyy_MM_dd"));
}
@Override
public Collection<String> doSharding(Collection<String> availableTargetNames, RangeShardingValue<Date> rangeShardingValue) {
Range<Date> valueRange = rangeShardingValue.getValueRange();
Date lowerDate = valueRange.lowerEndpoint();
Date upperDate = valueRange.upperEndpoint();
List<String> tableNameList = new ArrayList<>();
for (DateTime dateTime : DateUtil.rangeToList(DateUtil.beginOfDay(lowerDate), DateUtil.endOfDay(upperDate), DateField.DAY_OF_YEAR)) {
String resultTableName = rangeShardingValue.getLogicTableName() + DateUtil.format(dateTime, "_yyyy_MM_dd");
if (shardingTablesExistsCheck(resultTableName)) {
tableNameList.add(resultTableName);
}
}
return tableNameList;
}
}
项目启动时将表载入缓存/注入工具类属性 ShardingTablesLoadRunner
import com.**.**.config.sharding.ShardingAlgorithmTool;
import com.**.**.dao.CommonMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Slf4j
@Order(value = 1)
@Component
public class ShardingTablesLoadRunner implements CommandLineRunner {
@Value("${db.schema-name}")
private String schemaName;
@Resource
private CommonMapper commonMapper;
@Override
public void run(String... args) throws Exception {
ShardingAlgorithmTool.setCommonMapper(commonMapper);
ShardingAlgorithmTool.tableNameCacheReload(schemaName);
log.info("ShardingTablesLoadRunner start OK");
}
}
Mybatis SQL 映射 CommonMapper
import com.**.**.domain.db.CreateTableSql;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface CommonMapper {
List<String> getAllTableNameBySchema(@Param("schema") String schema);
CreateTableSql selectTableCreateSql(@Param("tableName") String tableName);
void executeSql(@Param("sql") String sql);
}
Mybatis SQL 映射 XML CommonMapper
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.**.**.dao.CommonMapper">
<resultMap id="selectTableCreateSqlResultMap" type="com.**.**.domain.db.CreateTableSql">
<result column="Table" property="table"/>
<result column="Create Table" property="createTable"/>
</resultMap>
<select id="getAllTableNameBySchema" resultType="java.lang.String">
SELECT TABLES.TABLE_NAME
FROM information_schema.TABLES
WHERE TABLES.TABLE_SCHEMA = #{schema}
</select>
<select id="selectTableCreateSql" resultMap="selectTableCreateSqlResultMap">
SHOW CREATE TABLE ${tableName}
</select>
<update id="executeSql">
${sql}
</update>
</mapper>
Mybatis SQL 映射实体 CreateTableSql
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CreateTableSql {
private String table;
private String createTable;
}
出处:https://www.cnblogs.com/heei/p/15167024.html