Mybatis-plus动态表名配置

一、pom文件依赖

        
            com.baomidou
            mybatis-plus-boot-starter
            3.5.1
        

二 、mybatis配置类

2.1 表名设置工具类 TableNameHelper

package com.example.boot.config;


public class TableNameHelper {
	/**
	 * 请求参数存取
	 */
	private static final ThreadLocal TABLE_NAME = new ThreadLocal<>(); //保证线程安全

	/**
	 * 批量语句
	 */
	private static final ThreadLocal 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;
	}
}

2.2 mybatis config类  MybatisPlusConfig

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配置类中获取到我们设置的表名,从而实现动态表名的功能。

2.3 表名生成工具类 TableNameGenerator

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  分表类型
	 * @return tableNames 表名集合
	 * @description: 按照 分表类型 和 时间范围 获取表名集合
	 * @author xxz
	 */
	public static List generateTables(String baseTableName, LocalDateTime startTime, LocalDateTime endTime, SubtableType subtableType) {
		List 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 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 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 tables3 = generateTables(baseTableName, startTime3, endTime3, SubtableType.BY_YEAR);
		System.out.println(tables3);
	}
}


 

你可能感兴趣的:(mybatis,java,前端)