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
相关推荐
zquwei14 分钟前
SpringCloudGateway+Nacos注册与转发Netty+WebSocket
java·网络·分布式·后端·websocket·网络协议·spring
TT哇21 分钟前
*【每日一题 提高题】[蓝桥杯 2022 国 A] 选素数
java·算法·蓝桥杯
火烧屁屁啦43 分钟前
【JavaEE进阶】初始Spring Web MVC
java·spring·java-ee
飞飞-躺着更舒服1 小时前
【QT】实现电子飞行显示器(改进版)
开发语言·qt
w_31234541 小时前
自定义一个maven骨架 | 最佳实践
java·maven·intellij-idea
岁岁岁平安1 小时前
spring学习(spring-DI(字符串或对象引用注入、集合注入)(XML配置))
java·学习·spring·依赖注入·集合注入·基本数据类型注入·引用数据类型注入
武昌库里写JAVA1 小时前
Java成长之路(一)--SpringBoot基础学习--SpringBoot代码测试
java·开发语言·spring boot·学习·课程设计
Q_19284999061 小时前
基于Spring Boot的九州美食城商户一体化系统
java·spring boot·后端
张国荣家的弟弟1 小时前
【Yonghong 企业日常问题 06】上传的文件不在白名单,修改allow.jar.digest属性添加允许上传的文件SH256值?
java·jar·bi
ZSYP-S2 小时前
Day 15:Spring 框架基础
java·开发语言·数据结构·后端·spring