业务场景
在为某新能源汽车厂商进行我司系统私有化部署时,在预演环境和生产环境中,客户仅提供了一个 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;
}
}