基于MyBatis插件实现动态表名解决多环境单一数据库问题

业务场景

在为某新能源汽车厂商进行我司系统私有化部署时,在预演环境和生产环境中,客户仅提供了一个 MySQL 数据库实例。为了确保数据隔离并避免不同环境之间的数据冲突,常规做法是为每个环境创建独立的表(如通过添加环境前缀或后缀)。

然而,如果每次切换环境都需要手动修改 SQL 或配置文件中的表名,不仅效率低下,而且容易出错。为此,小编利用 MyBatis 插件机制 实现了动态表名替换,从而优雅地解决了多环境共用数据库的问题。

解决方案

java 复制代码
/**
 * 动态表名工具参数
 *
 * @author 言安
 * @date 2025/3/20 14:37
 */
@Data
@Component
@ConfigurationProperties(prefix = SpongeDynamicTableNameProperties.PREFIX)
public class SpongeDynamicTableNameProperties {

    public static final String PREFIX = "sponge.dynamic";

    /**
     * 是否开启
     */
    private Boolean enable = Boolean.FALSE;
    /**
     * 默认表名后缀
     */
    private String defaultTableNameSuffix;
    /**
     * 表名后缀映射(key:表名, value: 后缀)
     * 优先取表名后缀映射,取不到取 defaultTableNameSuffix
     */
    private Map<String, String> tableNameSuffixMap;
}
java 复制代码
/**
 * 动态表名处理器
 *
 * @author 言安
 * @date 2025/3/20 13:41
 */
@Component
public class SpongeDynamicTableNameHandler implements TableNameHandler {


    // 默认后缀
    private final static String DEFAULT_SUFFIX = "_test";

    @Resource
    private SpongeDynamicTableNameProperties spongeDynamicTableNameProperties;

    @Override
    public String dynamicTableName(String sql, String tableName) {
        String suffix = DEFAULT_SUFFIX;
        if (spongeDynamicTableNameProperties != null) {
            if (spongeDynamicTableNameProperties.getDefaultTableNameSuffix() != null) {
                suffix = spongeDynamicTableNameProperties.getDefaultTableNameSuffix();
            }
            if (spongeDynamicTableNameProperties.getTableNameSuffixMap() != null && spongeDynamicTableNameProperties.getTableNameSuffixMap().containsKey(tableName)) {
                suffix = spongeDynamicTableNameProperties.getTableNameSuffixMap().get(tableName);
            }
        }
        return StringUtil.isBlank(suffix) ? tableName : tableName + suffix;
    }
}
java 复制代码
/**
 * MybatisPlus配置类
 *
 * @author 言安
 * @date 2025/3/20 13:41
 */
@Configuration
@EnableTransactionManagement
public class MybatisPlusConfiguration {

    @Resource
    private SpongeDynamicTableNameProperties spongeDynamicTableNameProperties;

    @Resource
    private SpongeDynamicTableNameHandler myTableNameHandler;

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        if (spongeDynamicTableNameProperties != null && Boolean.TRUE.equals(spongeDynamicTableNameProperties.getEnable())) {
            // 动态表名插件
            DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor = new DynamicTableNameInnerInterceptor();
            dynamicTableNameInnerInterceptor.setTableNameHandler(myTableNameHandler);
            interceptor.addInnerInterceptor(dynamicTableNameInnerInterceptor);
        }
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}
相关推荐
TDengine (老段)1 小时前
连接 TDengine 遇到报错 “failed to connect to server, reason: Connection refused” 怎么办?
大数据·数据库·物联网·时序数据库·iot·tdengine·涛思数据
李慕婉学姐2 小时前
Springboot黄河文化科普网站5q37v(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库·spring boot·后端
Cabbage_acmer3 小时前
MySQL期中考试突击!
数据库·mysql
Lu Yao_3 小时前
Redis 缓存
数据库·redis·缓存
小桥流水人家哇3 小时前
性能测试单场景测试时,是设置并发读多个文件,还是设置不同的用户读不同的文件?
数据库·性能测试技巧
表示这么伤脑筋的题我不会3 小时前
Oracle 21C 部署ogg踩过的坑
数据库·oracle
你不是我我3 小时前
【Java 开发日记】MySQL 与 Redis 如何保证双写一致性?
数据库·redis·缓存
望获linux3 小时前
【实时Linux实战系列】实时 Linux 在边缘计算网关中的应用
java·linux·服务器·前端·数据库·操作系统
fredinators4 小时前
数据库专家
大数据·数据库
fredinators4 小时前
数据库flask访问
数据库·oracle·flask