|
MyBatis-Plus中这样写@TableName(value = "${severcfgdata.tablename}"),会报错,找不到severcfgdata
在 MyBatis-Plus 中,@TableName 注解的 value 属性 不支持直接使用 ${} 占位符从配置文件中读取值(这与 Spring 的 @Value 注解不同)。以下是实现动态表名的两种方案:
方案一:通过动态表名处理器(推荐)
通过 MyBatis-Plus 的 动态表名功能 动态替换表名,而非直接在 @TableName 中硬编码。
1. 在 application.yml 中定义表名
yaml
Copy Code
severcfgdata:
tablename: fwd_files_prod # 根据环境动态配置
2. 创建动态表名处理器
java
Copy Code
public class DynamicTableNameHandler implements IDynamicTableNameHandler {
@Value("${severcfgdata.tablename}") // 直接注入配置值
private String targetTableName;
@Override
public String dynamicTableName(MetaObject metaObject, String sql, String originalTableName) {
// 如果原表名是实体类中写的固定值(如 "fwd_files"),则替换为配置值
return "fwd_files".equalsIgnoreCase(originalTableName) ? targetTableName : originalTableName;
}
}
3. 配置 MyBatis-Plus 拦截器
java
Copy Code
@Configuration
public class MyBatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 添加动态表名拦截器
DynamicTableNameInnerInterceptor dynamicInterceptor = new DynamicTableNameInnerInterceptor();
dynamicInterceptor.setTableNameHandler(new DynamicTableNameHandler());
interceptor.addInnerInterceptor(dynamicInterceptor);
return interceptor;
}
}
4. 实体类使用固定表名(与配置中的逻辑名匹配)
java
Copy Code
@TableName("fwd_files") // 固定表名,会被拦截器动态替换
public class FwdFiles {
// 实体字段定义
}
方案二:在应用启动时动态设置表名
通过 Spring 的 @PostConstruct 在应用启动时读取配置,并动态修改实体类的表名。
1. 定义配置类
java
Copy Code
@Component
public class TableNameConfig {
@Value("${severcfgdata.tablename}")
private String tableName;
@PostConstruct
public void setDynamicTableName() {
// 动态修改实体类的 @TableName 值
TableName annotation = FwdFiles.class.getAnnotation(TableName.class);
if (annotation != null) {
// 通过反射修改注解值
InvocationHandler handler = Proxy.getInvocationHandler(annotation);
Field field;
try {
field = handler.getClass().getDeclaredField("memberValues");
field.setAccessible(true);
Map<String, Object> memberValues = (Map<String, Object>) field.get(handler);
memberValues.put("value", tableName); // 覆盖表名
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
2. 实体类声明
java
Copy Code
@TableName("dummy_table") // 初始值会被动态覆盖
public class FwdFiles {
// 实体字段定义
}
3. 配置文件中定义表名
yaml
Copy Code
severcfgdata:
tablename: fwd_files_prod
为什么不能直接用 ${} 占位符?
MyBatis-Plus 的 @TableName 注解是 编译时静态解析 的,而 ${} 占位符需要 Spring 在运行时动态解析。两者机制不兼容,因此直接使用占位符会报错 severcfgdata not found。
总结
推荐方案一:通过动态表名处理器实现,符合 MyBatis-Plus 设计规范,无需反射黑魔法。
方案二:通过反射强制修改注解值,虽然可行但破坏封装性,且可能引发其他问题。
|
|