一、定义拦截器
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;}@Overridepublic 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);// 设置回MetaObjectmetaObject.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;@Beanpublic MybatisPlusInterceptor dynamicTableNameInnerInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new DynamicTableNameInterceptor(tableLibrary));return interceptor;}
}
三、配置文件修改
# 分表库
tableLibrary: asm_result,check_result
四、测试


