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 清除
相关推荐
谭光志14 小时前
Vibe Coding 时代,程序员该何去何从
前端·后端·ai编程
GoGeekBaird15 小时前
我用 BeeWeave 跑完了一次完整写作闭环
后端·github
仿生狮子16 小时前
别再说“全栈”了,AI 时代团队只认这 5 种人
前端·人工智能·后端
Reart19 小时前
Leetcode 213.打家劫舍2(内含闲谈,打劫真是技术活,好题,716)
后端·算法
触底反弹19 小时前
🔥 RAG 到底是怎么工作的?掰开揉碎了给你讲明白!
javascript·人工智能·后端
techdashen19 小时前
Go 1.26 新增 `bytes.Buffer.Peek`:只看数据,不移动读取位置
开发语言·后端·golang
Reart19 小时前
Leetcode 198.打家劫舍(716)
后端·算法
Java编程爱好者20 小时前
Spring6.0+Boot3.0:秒级启动、万级并发的开发新姿势
后端
YYYing.20 小时前
【C++大型项目之高性能服务器框架 (七) 】Socket与ByteArray模块
服务器·c++·后端·框架·高性能·c/c++
青山木20 小时前
一把 Redis 分布式锁,踩透四个坑:锁争抢、僵尸锁、锁过期、锁丢失
java·数据库·redis·后端