一、定义拦截器
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import java.math.BigDecimal;
import java.sql.Connection;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* @Intercepts({ })
* 这个注解用于标记一个类是一个MyBatis拦截器。
* 它包含一个或多个@Signature注解,用于指定拦截的目标方法。
*/
@Intercepts({
@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})
})
@Slf4j
public class DynamicTableNameInterceptor implements InnerInterceptor {
private String tableLibrary;
public DynamicTableNameInterceptor(String tableLibrary) {
this.tableLibrary = tableLibrary;
}
@Override
public void beforePrepare(StatementHandler statementHandler, Connection connection, Integer transactionTimeout) {
MetaObject metaObject = SystemMetaObject.forObject(statementHandler);// MetaObject 是MyBatis提供的一个工具类,用于通过反射操作对象的属性
BoundSql boundSql = statementHandler.getBoundSql();
String sql = boundSql.getSql();// 获取原始SQL语句
Object parameterObject = boundSql.getParameterObject();// 获取参数对象
String custom = null;
String customYear = null;
if (parameterObject instanceof Map) {
Map<String, Object> paramMap = (Map<String, Object>) parameterObject;
customYear = paramMap.containsKey("customYear") ? (String) paramMap.get("customYear") : null;
custom = paramMap.containsKey("custom") ? (String) paramMap.get("custom") : null;
} else if(
!(parameterObject instanceof String)
&& !(parameterObject instanceof Integer)
&& !(parameterObject instanceof Long)
&& !(parameterObject instanceof Double)
&& !(parameterObject instanceof BigDecimal)
&& !(parameterObject instanceof Date)
&& !(parameterObject instanceof Boolean)
) {
JSONObject json = new JSONObject(parameterObject);
customYear = json.containsKey("customYear") ? (String) json.get("customYear") : null;
custom = json.containsKey("custom") ? (String) json.get("custom") : null;
}
// custom为true表示不需要替换表名
if("true".equals(custom)){
return;
}
String replaceYear;
if (StringUtils.isEmpty(customYear)) {
replaceYear = String.valueOf(DateUtil.year(new Date()));// 获取当前年份
} else {
replaceYear = customYear;
}
String modifiedSql = modifyTableName(sql,replaceYear);
// 设置回MetaObject
metaObject.setValue("delegate.boundSql.sql", modifiedSql);
}
/**
* 替换表名
* @param sql 需要替换的 SQL
* @param replaceYear 表名的年份
* @return modifiedSql 替换之后的 SQL
*/
private String modifyTableName(String sql,String replaceYear) {
String modifiedSql = sql;
List<String> tableLibraries = Arrays.asList(tableLibrary.split(","));
if (!CollectionUtils.isEmpty(tableLibraries)) {
for (String table : tableLibraries) {
String newTableName = table + "_" + replaceYear;// 构造新表名
modifiedSql = modifiedSql.replace(table, newTableName); // modifiedSql中存放修改之后的sql
}
}
return modifiedSql;
}
}
二、注册拦截器
@Configuration
public class MybatisPlusConfig {
@Value("${tableLibrary:}")
private String tableLibrary;
@Bean
public MybatisPlusInterceptor dynamicTableNameInnerInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new DynamicTableNameInterceptor(tableLibrary));
return interceptor;
}
}
三、配置文件修改
# 分表库
tableLibrary: asm_result,check_result
四、测试


