一、概述
本项目基于 MyBatis-Plus DynamicTableNameInnerInterceptor 实现动态分表,核心思路是:在 SQL 执行前,通过 ThreadLocal 传递表名后缀,拦截器自动将逻辑表名替换为物理表名,从而实现多端数据隔离(如微信端 t_product_wechat、Web 端 t_product_web)。
二、核心类职责
| 类 | 路径 | 职责 |
|---|---|---|
ShardInteConfig |
biz/config/ShardInteConfig.java |
配置类,注册拦截器并绑定 Handler |
TableShardHandler |
biz/handle/TableShardHandler.java |
拦截器回调,执行表名拼接 |
DataShardStrategyHelper |
biz/handle/DataShardStrategyHelper.java |
ThreadLocal 工具类,存取/清除后缀 |
ShardTableConfig |
biz/config/properties/ShardTableConfig.java |
配置属性,定义默认后缀值 |
三、调用链路
scss
业务方法 → setShardType(type) → setShardingTableSuffix(suffix)
↓ (ThreadLocal 存储)
MyBatis 执行 SQL
↓
DynamicTableNameInnerInterceptor 拦截
↓
TableShardHandler.dynamicTableName(sql, tableName)
↓
tableName + "_" + suffix → 实际物理表名
↓
业务方法 finally → clearShardType()
四、各层详细逻辑
4.1 配置层
java
@Bean("shardingMybatisPlusInterceptor")
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
DynamicTableNameInnerInterceptor interceptor = new DynamicTableNameInnerInterceptor();
interceptor.setTableNameHandler(new TableShardHandler());
interceptor.addInnerInterceptor(interceptor);
return interceptor;
}
4.2 拦截层
java
@Override
public String dynamicTableName(String sql, String tableName) {
return tableShard(tableName);
}
public String tableShard(String tableName) {
String suffix = DataShardStrategyHelper.getShardingTableSuffix();
if (ObjectUtil.isNotEmpty(suffix)) {
return tableName + "_" + suffix;
}
return tableName;
}
4.3 上下文传递层
java
private static ThreadLocal<String> shardingTableSuffix = new ThreadLocal<>();
public static void setShardingTableSuffix(String suffix) // 设置
public static String getShardingTableSuffix() // 获取
public static void clearShardingTableSuffix() // 清除
五、业务使用模式
java
public List<XxxResponse> someMethod(String type) {
try {
if (StringUtils.isBlank(type)) {
type = shardTableConfig.getWechatTableType();
}
setShardType(type);
// 执行数据库操作...
} finally {
clearShardType();
}
}
六、分表效果示例
| type 参数 | 实际查询表 |
|---|---|
"wechat" |
t_product_wechat |
"web" |
t_product_web |
null |
t_product_wechat(默认) |
七、设计特点
- 线程安全:基于 ThreadLocal,请求线程独立
- 侵入小:业务方法前后 set/clear,Mapper 层无感知
- 灵活路由:请求参数动态决定分表
- 防御性编程:finally 确保 ThreadLocal 清除