MybatisPlus设置动态表名

对于一些数据量比较大的表,为了提高查询性能,我们一般将表拆分成多张表,常见的是根据数据量,按年分表或者按月分表;分表虽然太高了查询性能,但是在查询的时候,如何才能查询执行分表数据呢,这里整理了一下,使用MybatisPlus设置动态表名的功能实现

增加MyBatisPlus配置类

java 复制代码
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.handler.TableNameHandler;
import com.baomidou.mybatisplus.extension.plugins.inner.DynamicTableNameInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;

@Configuration
public class MyBatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();

        DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor = new DynamicTableNameInnerInterceptor();

        HashMap<String, TableNameHandler> map = new HashMap<>();
        map.put("my_test", (sql, tableName) -> DynamicTableTreadLocal.INSTANCE.getTableName());
        
        // 如果存在多张分表,则在下面添加多条记录

        dynamicTableNameInnerInterceptor.setTableNameHandlerMap(map);
        mybatisPlusInterceptor.addInnerInterceptor(dynamicTableNameInnerInterceptor);

        return mybatisPlusInterceptor;
    }

}
方法解析
MybatisPlusInterceptor

该插件是核心插件,目前代理了 Executor#queryExecutor#updateStatementHandler#prepare 方法

方法属性
复制代码
private List<InnerInterceptor> interceptors = new ArrayList<>();
InnerInterceptor接口

目前已有的功能:

  • 自动分页: PaginationInnerInterceptor
  • 多租户: TenantLineInnerInterceptor
  • 动态表名: DynamicTableNameInnerInterceptor
  • 乐观锁: OptimisticLockerInnerInterceptor
  • sql 性能规范: IllegalSQLInnerInterceptor
  • 防止全表更新与删除: BlockAttackInnerInterceptor
注意事项

使用多个功能需要注意顺序关系,建议使用如下顺序

  • 多租户,动态表名
  • 分页,乐观锁
  • sql 性能规范,防止全表更新与删除

总结: 对 sql 进行单次改造的优先放入,不对 sql 进行改造的最后放入

增加本地动态线程设置表名

java 复制代码
public enum DynamicTableTreadLocal {
    INSTANCE;
    private ThreadLocal<String> tableName = new ThreadLocal<>();
    public String getTableName() {
        return tableName.get();
    }
    public void setTableName(String tableName) {
        this.tableName.set(tableName);
    }
    public void remove() {
        tableName.remove();
    }
}

DynamicTableTreadLocal类的作用是为每个线程提供一个独立的tableName变量。每个线程可以通过调用getTableName方法获取自己的tableName变量的值,也可以通过调用setTableName方法设置自己的tableName变量的值。这样可以保证每个线程都有自己独立的tableName变量,不会相互干扰。

ThreadLocal在该类中的作用

ThreadLocal是Java中的一个类,它提供了线程本地变量的功能。在DynamicTableTreadLocal类中,通过创建一个ThreadLocal对象tableName,每个线程都可以通过这个对象来获取和设置自己的tableName变量。ThreadLocal保证了每个线程都有自己独立的变量副本,不会被其他线程访问或修改。

ThreadLocal应用场景

ThreadLocal的应用场景主要是在多线程环境下,需要为每个线程维护独立的变量副本的情况下使用。例如,在Web应用中,每个请求都会被分配给一个线程进行处理,如果需要在处理请求的过程中保存一些状态信息,可以使用ThreadLocal来实现。另外,ThreadLocal还可以用于线程池、数据库连接池等场景,保证每个线程都有自己独立的资源。

表对应的的实体类配置

java 复制代码
@Data
@TableName("my_test")
@JsonInclude(JsonInclude.Include.NON_NULL)
public class MyTest implements Serializable {
    private static final long serialVersionUID = -65257563878624647L;

    @TableId("uuid")
    private String uuid;
    
    @JsonProperty("user_name")
    @TableField("user_name")
    private String userName;
}

在表对应的的实体类上,只需要配置没有分年月的表名@TableName("my_test")即可,无需指定分年月的表名;具体通过MyBatisPlusConfig类,根据DynamicTableTreadLocal类设置的表名自动切换要操作的表名

动态切换表的具体使用

设置表名
java 复制代码
DynamicTableTreadLocal.INSTANCE.setTableName("mytest_202401");
获取表名
java 复制代码
DynamicTableTreadLocal.INSTANCE.getTableName();
删除表名
java 复制代码
DynamicTableTreadLocal.INSTANCE.remove();

最后总结

文章参考MyBatis-Plus官方文档,根据具体业务需求修改实现

官方文档地址
url 复制代码
https://baomidou.com/
动态表名插件
url 复制代码
https://gitee.com/baomidou/mybatis-plus-samples/tree/master/mybatis-plus-sample-dynamic-tablename
相关推荐
运维行者_几秒前
MSP网络管理破局者:IPAM+SPM插件终结IP冲突与安全威胁
运维·服务器·开发语言·网络·安全·web安全·php
人间打气筒(Ada)几秒前
「码动四季·开源同行」go语言:如何处理 Go 错误异常与并发陷阱?
开发语言·后端·golang·defer·panic·errors·并发陷阱
wjcroom2 分钟前
电子python模拟出的一个完美风暴
开发语言·python·数学建模·物理学
aini_lovee2 分钟前
基于多时间尺度滚动优化的多能源微网双层调度模型(MATLAB实现)
开发语言·matlab·能源
极创信息3 分钟前
不同开发语言程序如何做信创适配认证?完整流程与评价指标有哪些
java·c语言·开发语言·python·php·ruby·hibernate
女王大人万岁4 分钟前
Golang实战gin-swagger:自动生成API文档
服务器·开发语言·后端·golang·gin
Seven975 分钟前
用300行代码手写SpringBoot核心原理
java
wregjru10 分钟前
【MySQL】5. 数据更新与查询详解
java·数据库·mysql
洛阳吕工11 分钟前
【Python 教程】无人机 MAVLink 通信完整实战:连接飞控、接收数据与发送指令
开发语言·python·无人机
小辉同志11 分钟前
79. 单词搜索
开发语言·c++·leetcode·回溯