MyBatis-Plus 动态分表实战:基于 DynamicTableNameInnerInterceptor 的多端数据隔离方案

一、概述

本项目基于 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(默认)

七、设计特点

  1. 线程安全:基于 ThreadLocal,请求线程独立
  2. 侵入小:业务方法前后 set/clear,Mapper 层无感知
  3. 灵活路由:请求参数动态决定分表
  4. 防御性编程:finally 确保 ThreadLocal 清除
相关推荐
程序员cxuan1 小时前
速度太快了!本地可以跑 DeepSeek-V4-Flash 了
人工智能·后端·程序员
阿祖zu2 小时前
芝士就是力量!开源私有化部署与 GitHub 双向同步的个人知识笔记 App
前端·后端·ios
不才不才不不才2 小时前
Spring 源码系列(16): doDispatch 全流程——一次请求的主干链路
java·后端·spring
IT_陈寒2 小时前
SpringBoot自动配置失效?这个隐藏配置坑了我一整晚
前端·人工智能·后端
搜狐技术产品小编20232 小时前
告别“黑盒”与误判:如何用“多智能体对抗辩论”重构内容安全审核系统
后端·多agent
DantyWei3 小时前
controller注册及调用时机
后端
edwarddamon3 小时前
Spring Cloud 配置热更新与 Bean 代理机制梳理
java·后端
码事漫谈3 小时前
我用 Seed Evolving 做了个 AI 小说写作工具
后端
Raas1004 小时前
MAIGateway,魔芋企业级AI网关的FinAPI成本竞争力设计
java·后端·网关·api网关·魔芋ai·finapi·mai gateway
计算机魔术师4 小时前
传统基础架构 - 微服务
大数据·后端·微服务·架构·开发工具·编程语言