MP设置动态表名

Mybatis设置动态表名

  • Mybatis设置动态表名
    • 1.动态表名插件
    • 2.传递表名
    • 3.注意事项

Mybatis设置动态表名

1.动态表名插件

MybatisPlus中提供了一个动态表名的插件:https://baomidou.com/pages/2a45ff/#dynamictablenameinnerinterceptor

插件的部分源码如下:

在这里插入图片描述

可见表名称动态获取就是依赖于 tableNameHandlerMapping 中的具体的TableNameHandler,这个Map如图:

在这里插入图片描述

这个Map的key是旧的表名称,value是TableNameHandler,就是表的名称处理器,用于根据旧名称获取新名称。

TableNameHandler的源码如下:

public interface TableNameHandler {

    /**
     * 生成动态表名
     *
     * @param sql       当前执行 SQL
     * @param tableName 表名
     * @return String
     */
    String dynamicTableName(String sql, String tableName);
}

OK,因此我们要做的事情就很简单了,定义DynamicTableNameInnterInterceptor,向其中添加一个TableNameHandler,将points_board这个表名,替换为points_board_赛季id的名称。

不过,新的问题来了,这个插件中的TableNameHandler该如何获取赛季对应的表名称呢?

计算表名的方式是获取获取上赛季时间,查询数据库中上赛季信息,得到上赛季id。然后拼接得到表名。

当我们批量的写数据到数据库时,如果每次插入都计算一次表名,那性能也太差了。因此,我们肯定是希望一次计算,在TableNameHandler中可以随时获取。

2.传递表名

假设业务流程如下:

在这里插入图片描述

流程中,我们会先计算表名,然后去执行持久化,而动态表名插件就会生效,去替换表名。

因此,一旦我们计算完表名,以某种方式传递给插件中的TableNameHandler,那么就无需重复计算表名了。

不过,问题来了:要知道动态表名称插件,以及TableNameHandler,都是由MybatisPlus内部调用的。我们无法传递参数。那么该如何传递表名称呢?

虽然无法传参,但是从计算表名,到动态表名插件执行,调用TableNameHandler,都是在一个线程内完成的。要在一个线程内实现数据共享,该用什么呢?

大家应该很容易想到,就是ThreadLocal我们可以在定时任务中计算完动态表名后,将表名存入ThreadLocal,然后在插件中从ThreadLocal中读取即可:

在这里插入图片描述

定义ThreadLocal

public class TableInfoContext {
    private static final ThreadLocal<String> TL = new ThreadLocal<>();

    public static void setInfo(String info) {
        TL.set(info);
    }

    public static String getInfo() {
        return TL.get();
    }

    public static void remove() {
        TL.remove();
    }
}

然后在定义一个配置类,用于定义 DynamicTableNameInnterInterceptor 插件:

import com.baomidou.mybatisplus.extension.plugins.handler.TableNameHandler;
import com.baomidou.mybatisplus.extension.plugins.inner.DynamicTableNameInnerInterceptor;
import com.tianji.learning.utils.TableInfoContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

@Configuration
public class MybatisConfiguration {

    @Bean
    public DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor() {
        // 准备一个Map,用于存储TableNameHandler
        Map<String, TableNameHandler> map = new HashMap<>(1);
        // 存入一个TableNameHandler,用来替换points_board表名称
        // 替换方式,就是从TableInfoContext中读取保存好的动态表名
        map.put("points_board", (sql, tableName) -> TableInfoContext.getInfo() == null ? tableName : TableInfoContext.getInfo());
        return new DynamicTableNameInnerInterceptor(map);
    }
}

插件虽然定义好了,但是该如何继承到MybatisPlus中呢?

实现MybatisPlus的自动装配,并且定义了MP插件,将DynamicTableNameInnerInterceptor配置进去。

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
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.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@ConditionalOnClass({MybatisPlusInterceptor.class, BaseMapper.class})
public class MybatisConfig {

    /**
     * @see MyBatisAutoFillInterceptor 通过自定义拦截器来实现自动注入creater和updater
     * @deprecated 存在任务更新数据导致updater写入0或null的问题,暂时废弃
     */
    // @Bean
    // @ConditionalOnMissingBean
    public BaseMetaObjectHandler baseMetaObjectHandler() {
        return new BaseMetaObjectHandler();
    }

    /**
     * 配置 mybatis plus拦截器链
     *
     * @return
     */
    @Bean
    @ConditionalOnMissingBean
    public MybatisPlusInterceptor mybatisPlusInterceptor
    //声明 DynamicTableNameInnerInterceptor 并不是必须的,毕竟不是所有的服务都需要这个动态插件
    (@Autowired(required = false) DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor) {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
        paginationInnerInterceptor.setMaxLimit(200L);
        if (dynamicTableNameInnerInterceptor != null){
            //说明声明了该拦截器,需要加入到 mybatis plus的拦截器链中
            interceptor.addInnerInterceptor(dynamicTableNameInnerInterceptor);
        }
        interceptor.addInnerInterceptor(paginationInnerInterceptor);//分页拦截器插件
        interceptor.addInnerInterceptor(new MyBatisAutoFillInterceptor());
        return interceptor;
    }
}

配置自动装配 META-INF/spring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
 com.tianji.common.autoconfigure.mybatis.MybatisConfig\

3.注意事项

注意:

  • 由于DynamicTableNameInnerInterceptor并不是每一个微服务都用了,所以这里加入了@Autowired(required = false),避免未定义该拦截器的微服务报错。

  • MybatisPlus的插件定义顺序非常重要,必须按照一定的顺序来定义。参考:https://baomidou.com/pages/2976a3/#innerinterceptor

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/504174.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

大模型面试准备(十):大模型数据处理方法及优秀的开源数据介绍

节前&#xff0c;我们组织了一场算法岗技术&面试讨论会&#xff0c;邀请了一些互联网大厂朋友、参加社招和校招面试的同学&#xff0c;针对大模型技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何备战、面试常考点分享等热门话题进行了深入的讨论。 合集在这…

【Consul】Linux安装Consul保姆级教程

【Consul】Linux安装Consul保姆级教程 大家好 我是寸铁&#x1f44a; 总结了一篇【Consul】Linux安装Consul保姆级教程✨ 喜欢的小伙伴可以点点关注 &#x1f49d; 前言 今天要把编写的go程序放到linux上进行测试Consul服务注册与发现&#xff0c;那怎么样才能实现这一过程&am…

内网渗透之域环境探索和简单提权

参考文章&#xff1a;http://t.csdnimg.cn/AZ2OR 一个简单的域环境可以这样子搭建&#xff1a; 其中边界服务器有两张网卡&#xff0c;一个是对外的公网网卡&#xff0c;另一张是对内的局域网网卡。一般渗透过程中&#xff0c;拿下这个作为跳板机&#xff0c;进而继续渗透。 …

P23—P25:标识符和关键字

标识符 什么是标识符&#xff1f; 在java源程序中&#xff0c;程序员有权自己命名的单词都是标识符在EditPlus编译器中&#xff0c;表示符以黑色高亮字体显示 标识符可以标识什么元素&#xff1f; 类名方法名变量名接口名常量名 … 标识符的命名规则&#xff1a; 只能由**数…

C++学习随笔(8)——模板初阶

本章我们来学习一下C的模版部分&#xff01; 目录 1. 泛型编程 2. 函数模板 2.1 函数模板概念 2.1 函数模板格式 2.3 函数模板的原理 2.4 函数模板的实例化 2.5 模板参数的匹配原则 3. 类模板 3.1 类模板的定义格式 3.2 类模板的实例化 1. 泛型编程 如何实现一个通…

Android vehicle车辆属性新增demo

目录 前言一、Vehicle模块1.1 简介1.2 Vehicle框架1.3 主要功能和特点1.4 重要服务CarService1.4.1 简介1.4.2 组成1.4.3 启动时序1.4.4 作用 二、车辆属性新增demo2.1 CarPropertyService2.1.1 简介2.1.2 架构2.1.3 车辆属性 API2.1.4 CarPropertyService 初始化流程 2.2 App …

鸿蒙ARKTS--简易的购物网站

目录 一、media 二、string.json文件 三、pages 3.1 登录页面&#xff1a;gouwuPage.ets 3.2 PageResource.ets 3.3 商品页面&#xff1a;shangpinPage.ets 3.4 我的页面&#xff1a;wodePage.ets 3.5 注册页面&#xff1a;zhucePage.ets 3. 购物网站主页面&#xff…

在GitHub上上传项目(Idea)

repository创建好后&#xff0c;GitHub会提示相应的命令 在Idea的终端执行这些命令&#xff0c;就OK了 在GitHub上查看&#xff0c;已经上传成功

设备树语法

设备树语法 1 Devicetree格式1.1 DTS文件格式1.2 node格式1.3 properties格式 2 dts文件包好desi文件3 常用的 属性 properties3.1 #address-cells、#size-cells3.2 compatible3.3 model3.4 status3.5 reg&#xff08;设备不同reg属性的含义就不同&#xff09;3.6 name、device…

企业知识库搭建不再是难题,靠这几个软件就可以了

在当今知识为王的时代&#xff0c;具备一套强大且实用的企业知识库&#xff08;Knowledge Base&#xff09;已成为提升工作效率、促进团队合作不可或缺的工具。那么&#xff0c;问题来了&#xff0c;我们该如何搭建一套属于自己的知识库呢&#xff1f;今天&#xff0c;我就给大…

软件工程 - 04 需求分析

文章目录 需求分析需求分析方法系统建模用例图类图对象图活动图时序图协作图构件图部署图 软件开发各个阶段的图 需求分析 软件开发中非常重要的一环&#xff1b;好的需求分析方法&#xff0c;可以帮助更好地理解用户需求&#xff0c;准确定义系统的功能和性能要求&#xff0c…

深入理解数据结构(3):栈和队列详解

文章主题&#xff1a;顺序表和链表详解&#x1f331;所属专栏&#xff1a;深入理解数据结构&#x1f4d8;作者简介&#xff1a;更新有关深入理解数据结构知识的博主一枚&#xff0c;记录分享自己对数据结构的深入解读。&#x1f604;个人主页&#xff1a;[₽]的个人主页&#x…

系统优化都没做过?看这篇就够了

目录 一、系统优化指标 二、系统优化简介 三、系统优化 3.1 CPU 高 3.2 内存占用高 业务引起的内存升高 程序自身引起的内存问题 3.3 磁盘I/O 3.4 网络 3.5 数据库优化 3.6 响应时间高 3.7 吞吐量 3.8 代码层面优化 3.9 业务优化 四、JVM优化 4.1 堆内存设置 4.2 选择何时的…

半导体工艺技术

完整内容点击&#xff1a;【半导体工艺技术】

win10蓝牙开关不见了怎么办,win10设置里面蓝牙开关不见了

最近&#xff0c;有用户在使用win10系统的时候&#xff0c;发现设置蓝牙和其他设备中蓝牙开关不见了。正常情况下&#xff0c;“蓝牙和其他设备”下面是有蓝牙开启开关的&#xff0c;没有的话是怎么回事呢?出现这样的情况&#xff0c;可能是应为系统没有将测到蓝牙设备或者蓝牙…

高德地图key注册教程_地图数据采集软件

1.先注册成为开发者账号。 2.再申请高德地图Key。 3.把申请得到的高德地图Key填入软件中。 1.请先打开以下连接 高德地图key注册地址 易地图数据采集大师手机App版介绍 易地图数据采集大师电脑PC版介绍 2.注册新用&#xff08;如果已有开发者账号&#xff0c;本步可省略&am…

知识蒸馏详解及pytorch官网demo案例

知识蒸馏Knowledge Distillation(KD) 1、简介 一种模型压缩方法 知识蒸馏的一般框架&#xff08;如下图&#xff09; 三部分&#xff1a;知识、蒸馏算法、师生架构。 知识 将知识分为三种形式&#xff1a;基于响应的&#xff08;response-based&#xff09;、基于特征的&…

pytest--python的一种测试框架--pytest常用断言类型

一、pytest常用断言类型 等于: 不等于&#xff1a;&#xff01; 大于&#xff1a;> 小于&#xff1a;< 属于&#xff1a;in 不属于&#xff1a;not in 大于等于&#xff1a;> 小于等于&#xff1a;< 是&#xff1a;is 不是&#xff1a;is not def test_two():ass…

酷得单片机方案 2.4G儿童遥控漂移车

电子方案开发定制&#xff0c;我们是专业的 东莞酷得智能单片机方案之2.4G遥控玩具童车具有以下比较有特色的特点&#xff1a; 1、内置充电电池&#xff1a;这款小车配备了可充电的电池&#xff0c;无需频繁更换电池&#xff0c;既环保又方便。充电方式可能为USB充电或者专用…

LATTICE进阶篇DDR2--(0)获取ddr2 IP核

前言 想要仿真lattice的DDR2由来已久&#xff0c;但苦于对其了解甚少&#xff0c;在查阅过很多资料后&#xff0c;终于对这个IP核的仿真有了一些了解。 现做一些总结&#xff0c;以备不时之需&#xff0c;也让有需要的朋友&#xff0c;少走一些弯路。 环境&#xff1a;win10…