Fork me on GitHub

MybatisPlus动态表名

官网文档

https://baomidou.com/plugins/dynamic-table-name/

Java代码

配置拦截器

import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.DynamicTableNameInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * MyBatis Plus 配置
 * 动态表名插件
 */
@Configuration
public class MyBatisPlusConfig {

    public static ThreadLocal<String> tableNameHolder = new ThreadLocal<>();

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 添加动态表名插件
        DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor = new DynamicTableNameInnerInterceptor();
        dynamicTableNameInnerInterceptor.setTableNameHandler((sql, tableName) -> {
            // 从 ThreadLocal 中获取动态表名
            String dynamicTableName = tableNameHolder.get();
            if (dynamicTableName != null) {
                return dynamicTableName; // 返回动态表名
            }
            return tableName; // 默认表名
        });
        interceptor.addInnerInterceptor(dynamicTableNameInnerInterceptor);
        return interceptor;
    }


    /**
     * 生成动态表名
     * @param originalTableName 原表名
     * @param cityid 城市
     * @return 动态表名
     */
    public static String generateDynamicTableName(String originalTableName, String cityid) {
        // 获取当前年份
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
        String year = sdf.format(new Date());

        // 生成动态表名
        return originalTableName + "_" + cityid + "_" + year;
    }
}

使用动态表名

import com.baoer.terminaltcpserver.config.MyBatisPlusConfig;

public class SomeService {

    public void someMethod() {
        // 假设原表名为 "feedbacklog"
        String originalTableName = "feedbacklog";
        String cityid = "1";

        // 1.生成动态表名
        String dynamicTableName = MyBatisPlusConfig.generateDynamicTableName(originalTableName, cityid);
        // 2.设置到 ThreadLocal 中
        MyBatisPlusConfig.tableNameHolder.set(dynamicTableName);

        try {
            // 执行数据库操作
            // 例如:userMapper.selectList(null);
        } finally {

            // 3.清除 ThreadLocal 中的值
            MyBatisPlusConfig.tableNameHolder.remove();
        }
    }
}

拦截器无感替换表名

pom

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.3</version> <!-- 或项目现有版本,兼容 JDK 8 -->
</dependency>

动态表名处理器

package com.baoer.handler;

import com.baomidou.mybatisplus.extension.plugins.handler.TableNameHandler;
import com.lw.dillon.admin.framework.security.core.LoginUser;
import com.lw.dillon.admin.framework.security.core.util.SecurityFrameworkUtils;
import org.apache.commons.lang3.StringUtils;

import java.time.LocalDate;

/**
 * 流水数据动态表名处理器
 * 主表: device_data
 * 分表: device_data_{cityId}_{year}
 */
public class DynamicIbeDevDataTableNameHandler implements TableNameHandler {

    private static final String ORIGINAL_TABLE = "device_data";

    @Override
    public String dynamicTableName(String sql, String tableName) {
        if (!ORIGINAL_TABLE.equals(tableName)) {
            return tableName; // 只处理主表
        }

        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        if (loginUser == null || loginUser.getDeptId() == null) {
            // 未登录或区域id,返回主表(或抛异常/默认表)
            return ORIGINAL_TABLE;
        }

        String cityId = loginUser.getDeptId().toString();
        if (StringUtils.isBlank(cityId)) {
            return ORIGINAL_TABLE;
        }

        int year = LocalDate.now().getYear(); // 当前年份,如 2025

        return ORIGINAL_TABLE + "_" + cityId + "_" + year;
    }
}

MyBatis-Plus 配置类

package com.baoer.config;

import com.baoer.handler.DynamicDeviceDataTableNameHandler;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.DynamicTableNameInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MybatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        System.out.println("自定义表名替换 MybatisPlusInterceptor 已加载!");

        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();

        // 动态表名拦截器(必须在分页之前添加)
        DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor = new DynamicTableNameInnerInterceptor();
        dynamicTableNameInnerInterceptor.setTableNameHandler(new DynamicDeviceDataTableNameHandler());
        interceptor.addInnerInterceptor(dynamicTableNameInnerInterceptor);

        // 分页拦截器
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));

        return interceptor;
    }
}

配置类不生效(无打印)

@SpringBootApplication
@ComponentScan(basePackages = {"cn.iocoder.yudao", "com.autumn"}) // 添加你的自定义包
public class YudaoServerApplication { ... }

Bean 冲突(BeanDefinitionOverrideException)

框架已有 mybatisPlusInterceptor bean。
在 application.yml 添加:YAML

spring:
  main:
    allow-bean-definition-overriding: true
posted @ 2024-11-18 16:05  秋夜雨巷  阅读(176)  评论(0)    收藏  举报