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
相关推荐
脉动数据行情4 分钟前
Python 实现融通金行情数据对接(实时推送 + K 线 + 产品列表)
开发语言·python
DavidSoCool27 分钟前
Spring AI Alibaba ReactAgent 调用Tool 实现多轮对话
java·人工智能·spring·多轮对话·reactagent
skywalk816341 分钟前
Trae生成的中文编程语言关键字(如“定“、“函“、“印“等)需要和标识符之间用 空格 隔开,以确保正确识别
服务器·开发语言·编程
神所夸赞的夏天1 小时前
如何获取多层json数据,存成dictionary,并取最大最小值
java·前端·json
红色的小鳄鱼1 小时前
前端面试js手写
开发语言·前端·javascript
9号达人1 小时前
为什么你应该在 MQ 里用多个消费者,而不是一个
java·后端·架构
焦糖玛奇朵婷1 小时前
健身房预约小程序开发、设计
java·大数据·服务器·前端·小程序
海盗12341 小时前
C#中的IEqualityComparer<T>使用
开发语言·c#
小新同学^O^1 小时前
简单学习 --> TCP协议
java·网络·tcp
江公望1 小时前
Qt QSharedPointer用法,10分钟讲清楚
开发语言·qt