相关信息
使用场景:当实际业务会产生大量数据时使用分表操作,例如考勤信息按年月日分表、报表信息按年月日分表、也可以按实际业务产生的分类标识进行分表操作
配置类:
javapackage com.iagz.cloud.framework.mybatis.config;
import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.DynamicTableNameInnerInterceptor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.annotation.Bean;
import javax.sql.DataSource;
import java.sql.*;
@Slf4j
@AutoConfiguration(before = MybatisPlusAutoConfiguration.class)
public class MybatisPlusConfig {
// 使用ThreadLocal保存动态表名参数
private static final ThreadLocal<String> PARAM = new ThreadLocal<>();
public static void setParam(String param) {
PARAM.set(param);
}
public static void clearParam() {
PARAM.remove();
}
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(DataSource dataSource) {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 添加动态表名拦截器
interceptor.addInnerInterceptor(dynamicTableNameInnerInterceptor(dataSource));
log.info("MybatisPlusInterceptor 已创建并配置了动态表名拦截器");
// 可以添加其他拦截器
// interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
@Bean
public DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor(DataSource dataSource) {
DynamicTableNameInnerInterceptor interceptor = new DynamicTableNameInnerInterceptor();
interceptor.setTableNameHandler((sql, tableName) -> {
if ("模板表名".equals(tableName)) {
String param = PARAM.get();
if (param != null) {
String physicalTableName = "模板表名_" + param;
ensureTableExists(dataSource, physicalTableName);
return physicalTableName;
}
}
return tableName;
});
return interceptor;
}
// 确保表存在的方法
private synchronized void ensureTableExists(DataSource dataSource, String targetTableName) {
if (!checkTableExists(dataSource, targetTableName)) {
createTableFromTemplate(dataSource, targetTableName);
}
}
// 检查表是否存在
private boolean checkTableExists(DataSource dataSource, String tableName) {
try (Connection connection = dataSource.getConnection()) {
DatabaseMetaData metaData = connection.getMetaData();
try (ResultSet resultSet = metaData.getTables(null, null, tableName, new String[]{"TABLE"})) {
return resultSet.next();
}
} catch (SQLException e) {
throw new RuntimeException("检查表是否存在失败: " + tableName, e);
}
}
// 使用 CREATE TABLE ... LIKE 语法创建新表
private void createTableFromTemplate(DataSource dataSource, String targetTableName) {
String sourceTableName = "模板表名";
// 1. 首先检查源表是否存在
if (!checkTableExists(dataSource, sourceTableName)) {
throw new RuntimeException("模板表 " + sourceTableName + " 不存在,无法创建分表");
}
String createSql = "CREATE TABLE " + targetTableName + " LIKE " + sourceTableName;
try (Connection connection = dataSource.getConnection();
Statement statement = connection.createStatement()) {
statement.execute(createSql);
log.info("分表创建成功: {} (基于模板表: {})", targetTableName, sourceTableName);
} catch (SQLException e) {
throw new RuntimeException("创建分表失败: " + targetTableName, e);
}
}
}
service层调用方法
java@Service
public class YourService {
private final YourMapper yourMapper;
private final MybatisPlusConfig.TableManager tableManager;
public void yourMethod(String param) {
try {
// 设置动态表名参数
MybatisPlusConfig.setParam(param);
// 执行数据库操作
yourMapper.selectList(null);
} finally {
MybatisPlusConfig.clearPanelId();
}
}
}
本文作者:tiger
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!