<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>
package com.example.boot.config;
public class TableNameHelper {
/**
* 请求参数存取
*/
private static final ThreadLocal<String> TABLE_NAME = new ThreadLocal<>(); //保证线程安全
/**
* 批量语句
*/
private static final ThreadLocal<Integer> BATCH = new ThreadLocal<>();
/**
* 设置表名
*
* @param tableName 请求的表名
*/
public static void setTableName(String tableName) {
TABLE_NAME.set(tableName);
BATCH.set(0);
}
/**
* 设置批量更新的表名
*
* @param tableName 表名
*/
public static void setBatchTableName(String tableName) {
TABLE_NAME.set(tableName);
BATCH.set(1);
}
/**
* 移除表名
*/
public static void removeTableName() {
TABLE_NAME.remove();
BATCH.set(0);
}
/**
* 获取表名
*
* @return 请求的表名
*/
public static String getTableName() {
String s = TABLE_NAME.get();
if (BATCH.get() == null || BATCH.get() == 0) {
TABLE_NAME.remove(); // 使用一次后就清除数据,防止后续表名被篡改
}
return s;
}
}
package com.example.boot.config;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.DynamicTableNameInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @ClassName
* @Description TODO
* @Author 86136
* Date 2023/8/17 11:02
**/
@Configuration
@MapperScan("com.example.boot.mapper")
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
MybatisPlusInterceptor mybatisPlusInterceptor=new MybatisPlusInterceptor();
// 配置查询动态表名的拦截器,使用时先在TableNameHelper设置要查询的动态表名,然后直接执行mybatisplus的查询方法。注意赋予的动态表名只在一次查询中有效
DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor = new DynamicTableNameInnerInterceptor();
dynamicTableNameInnerInterceptor.setTableNameHandler(((sql, tableName) -> {
//获取表名方法
String newTableName = TableNameHelper.getTableName();
if (StrUtil.isNotBlank(newTableName)){
tableName = newTableName;
}
return tableName;
}));
mybatisPlusInterceptor.addInnerInterceptor(dynamicTableNameInnerInterceptor);
// 分页配置
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return mybatisPlusInterceptor;
}
}
设置动态表名时,实体类不需要写@TableName注解 需要在代码中手动设置表名。在代码中手动获取把时间拼接成表名,然后通过TableNameHelper.setTableName(),这样的话他会在config配置类中获取到我们设置的表名,从而实现动态表名的功能。
package com.skywalk.zktx.skywalk.common.mybatis.config; import lombok.extern.slf4j.Slf4j; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.List; @Slf4j public class TableNameGenerator { /** * @param baseTableName 基础表名 * @param startTime 开始时间 * @param endTime 结束时间 * @param subtableType 分表类型<SubtableType> * @return tableNames 表名集合 * @description: 按照 分表类型 和 时间范围 获取表名集合 * @author xxz */ public static List<String> generateTables(String baseTableName, LocalDateTime startTime, LocalDateTime endTime, SubtableType subtableType) { List<String> tableNames = new ArrayList<>(); if (startTime == null || endTime == null) { log.error("无法生成[{}]表名,开始时间[{}]或结束时间[{}]为null!", baseTableName, startTime, endTime); return tableNames; } if (startTime.isAfter(endTime)) { log.error("无法生成[{}]表名,开始时间[{}]在结束时间[{}]之后!", baseTableName, startTime, endTime); return tableNames; } DateTimeFormatter formatter; LocalDateTime current = startTime; switch (subtableType) { case BY_YEAR: current = current.withMonth(1).withDayOfMonth(1).truncatedTo(ChronoUnit.DAYS); formatter = DateTimeFormatter.ofPattern("yyyy"); break; case BY_MONTH: current = current.withDayOfMonth(1).truncatedTo(ChronoUnit.DAYS); formatter = DateTimeFormatter.ofPattern("yyyyMM"); break; case BY_DAY: current = current.truncatedTo(ChronoUnit.DAYS); formatter = DateTimeFormatter.ofPattern("yyyyMMdd"); break; default: throw new IllegalArgumentException("Invalid SubtableType"); } while (!current.isAfter(endTime)) { String tableName = baseTableName + "_" + current.format(formatter); tableNames.add(tableName); current = incrementDateTime(current, subtableType); } return tableNames; } private static LocalDateTime incrementDateTime(LocalDateTime dateTime, SubtableType subtableType) { switch (subtableType) { case BY_YEAR: return dateTime.plusYears(1); case BY_MONTH: return dateTime.plusMonths(1); case BY_DAY: return dateTime.plusDays(1); default: throw new IllegalArgumentException("Invalid SubtableType"); } } public static void main(String[] args) { // 示例用法 String baseTableName = "base"; LocalDateTime startTime1 = LocalDateTime.of(2023, 7, 1, 0, 0, 0); LocalDateTime endTime1 = LocalDateTime.of(2023, 7, 1, 0, 0, 0); List<String> tables1 = generateTables(baseTableName, startTime1, endTime1, SubtableType.BY_DAY); System.out.println(tables1); LocalDateTime startTime2 = LocalDateTime.of(2023, 7, 18, 10, 27, 35); LocalDateTime endTime2 = LocalDateTime.of(2023, 8, 1, 0, 0, 0); List<String> tables2 = generateTables(baseTableName, startTime2, endTime2, SubtableType.BY_MONTH); System.out.println(tables2); LocalDateTime startTime3 = LocalDateTime.of(2021, 8, 1, 10, 27, 35); LocalDateTime endTime3 = LocalDateTime.of(2023, 7, 3, 16, 18, 53); List<String> tables3 = generateTables(baseTableName, startTime3, endTime3, SubtableType.BY_YEAR); System.out.println(tables3); } }