对于一些数据量比力大的表,为了进步查询性能,我们一般将表拆分成多张表,常见的是根据数据量,按年分表或者按月分表;分表固然太高了查询性能,但是在查询的时候,怎样才能查询执行分表数据呢,这里整理了一下,使用MybatisPlus设置动态表名的功能实现
增加MyBatisPlus配置类
- 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#query 和 Executor#update 和 StatementHandler#prepare 方法
方法属性
- private List<InnerInterceptor> interceptors = new ArrayList<>();
复制代码 InnerInterceptor接口
如今已有的功能:
- 自动分页: PaginationInnerInterceptor
- 多租户: TenantLineInnerInterceptor
- 动态表名: DynamicTableNameInnerInterceptor
- 乐观锁: OptimisticLockerInnerInterceptor
- sql 性能规范: IllegalSQLInnerInterceptor
- 防止全表更新与删除: BlockAttackInnerInterceptor
留意事项
使用多个功能需要留意次序关系,发起使用如下次序
- 多租户,动态表名
- 分页,乐观锁
- sql 性能规范,防止全表更新与删除
总结: 对 sql 举行单次改造的优先放入,不对 sql 举行改造的末了放入
增加本地动态线程设置表名
- 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还可以用于线程池、数据库连接池等场景,保证每个线程都有自己独立的资源。
表对应的的实体类配置
- @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类设置的表名自动切换要操作的表名
动态切换表的具体使用
设置表名
- DynamicTableTreadLocal.INSTANCE.setTableName("mytest_202401");
复制代码 获取表名
- DynamicTableTreadLocal.INSTANCE.getTableName();
复制代码 删除表名
- DynamicTableTreadLocal.INSTANCE.remove();
复制代码 末了总结
文章参考MyBatis-Plus官方文档,根据具体业务需求修改实现
官方文档地点
动态表名插件
- https://gitee.com/baomidou/mybatis-plus-samples/tree/master/mybatis-plus-sample-dynamic-tablename
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |