mybatis-plus 实现查询表名动态修改的示例代码

2025-03-17 13:50

本文主要是介绍mybatis-plus 实现查询表名动态修改的示例代码,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《mybatis-plus实现查询表名动态修改的示例代码》通过MyBatis-Plus实现表名的动态替换,根据配置或入参选择不同的表,本文主要介绍了mybatis-plus实现查询表名动态修改的示...

通过 mybatis-plus 实现表名的动态替换,即通过配置或入参动态选择不同的表。

下面通过一个例子来说明该需求: 我们需要为学校开发一个成绩管理系统,需要建立三张表: 学生表、科目表和成绩表,表的 ER 图如下所示。

mybatis-plus 实现查询表名动态修改的示例代码

对应的建表语句如下:

-- 学科表
drop table if exists subject;
create table subject(id int primary key , name varchar(64));

-- 学生表
drop table if exists student;
create table student (id int primary key , name varchar(64));

-- 成绩表(学生-学科 多对多)
drop table if exists score;
create table score(id int primary key , student_id int, subject_id int, result int);

根据三张表级联查询成绩的查询语句为:

select subject.name as subject_name, student.name as student_name, score.result as score
    from score, student, subject where score.student_id=student.id and score.subject_id=subject.id;

现在又来了一个新需求,我们的这套成绩查询系统需要部署在不同学校的服务器上,因为每个学校的学生表和成绩表都要同步到教育局的服务器中,因此需要为这两个表添加学校前缀,ER 图如下所示。

mybatis-plus 实现查询表名动态修改的示例代码

不同学校的建表语句不同,对于 USTC 学校而言,建表语句为:

-- 学科表
drop table if exists subject;
create table subject(id int primary key , name varchar(64));

-- 学生表
drop table if exists ustc_student;
create table ustc_student (id int primary key , name varchar(64));

-- 成绩表(学生-学科 多对多)
drop table if exists ustc_score;
create table ustc_score(id int primary key , student_id int, subject_id int, result int);

对于 ZJU 学校而言,建表语句为:

-- 学科表
drop table if exists subject;
create table subject(id int primary key , name varchar(64));

-- 学生表
drop table if exists zju_student;
create table zju_student (id int primary key , name varchar(64));

-- 成绩表(学生-学科 多对多)
drop table if exists zju_score;
create table zju_score(id int primary key , student_id int, subject_id int, result int);

我们的成绩查询系统会安装在不同的学校,并且校名是动态可配的,因此该成绩查询系统需要根据配置文件动态修改 sql 语句表名的功能。

实现

源码地址: https://github.com/foolishflyfox/blog/tree/main/backend-code/mp-dynamic-tablename

数据库初始化

创建程序需要的表:

create database if not exists mp_dynamic_tablename_test;

use mp_dynamic_tablename_test;

-- 学科表
drop table if exists subject;
create table subject(id int primary key , name varchar(64));
insert into subject(id, name) values (1, 'Math'), (2, 'English'), (3, 'Chinese');

-- 学生表
drop table if exists student;
create table student (id int primary key , name varchar(64));
insert into student(id, name) values(1, 'aaa'), (2, 'bbb');

-- 成绩表(学生-学科 多对多)
drop table if exists score;
create table score(id int primary key , student_id int, subject_id int, result int);
insert into score(id, student_id, subject_id, result) values (1, 1, 1, 74), (2, 1, 2, 83), (3, 1, 3, 69),
    (4, 2, 1, 91), (5, 2, 3, 87);

-- 指定前缀 ustc 的表
-- 学生表
drop table if exists ustc_student;
create table ustc_student (id int primary key , name varchar(64));
insert into ustc_student(id, name) values(1, 'u_aaa'), (2, 'u_bbb');

-- 成绩表(学生-学科 多对多)
drop table if exists usphptc_score;
create table ustc_score(id int primary key , student_id int, subject_id int, result int);
insert into ustc_score(id, student_id, subject_id, result) values (1, 1, 1, 89), (2, 1, 2, 81), (3, 1, 3, 32),
                                                             (4, 2, 1, 71), (5, 2, 2, 77);

-- 指定前缀 zju 的表
-- 学生表
drop table if exists zju_student;
create table zju_student (id int primary key , name varchar(64));
insert into zju_student(id, name) values(5, 'z_aaa'), (6, 'z_bbb');

-- 成绩表(学生-学科 多对多)
drop table if exists zju_score;
create table zju_score(id int primary key , student_id int, subject_id int, result int);
insert into zju_score(id, student_id, subject_id, result) values (1, 5, 1, 91), (2, 5, 2, 66), (3, 5, 3, 85),
                                                                  (4, 6, 1, 48), (5, 6, 2, 59);

依赖包

需要引入 spring-boot-starter-web、spring-boot-starter-test、spring-boot-configuration-processor、mybatis-plus-boot-starter、mysql-connector-Java、lombok 库。

配置读取类

我们先定义一个配置读取类,用于获取动态配置的学校以及需要动态添加学校前缀的表名。

package cn.fff.config.properties;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.util.HashSet;
import java.util.Set;

@Component
@ConfigurationProperties("school")
@Data
public class SchoolProperties {
    /** 学校名,动态表名会添加前缀: 学校名_ */
    private String name;
    /** 需要动态添加前缀的表 */
    private Set<String> dynamicTables = new HashSet<>();
}

为 application.yml 添加如下配China编程置:

school:
  name: ustc
  dynamic-tables:
    - www.chinasem.cnstudent
    - score

表示需要为 student 和 score 动态添加前缀 ustc,即查询 student 表时会动态替换为 ustc_student,查询 score 表时会动态替换为 ustc_score。如果 school.name 修改为 zju,则查询 student 表时会动态替换为 zju_student,查询 score 表时会动态替换为 zju_score

设置 mybatis-plus 插件

实体类、mapper、服务类的创建比较基础,此处略过,可直接查看源码。动态表面主要通过创建一个 mybatis 插件实现:

package cn.fff.config.mp;

import cn.fff.config.properties.SchoolProperties;
iChina编程mport com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.DynamicTableNameInnerInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;

@Configuration
public class DynamicTableNameConfig {
    @Autowired
    private SchoolProperties schoolProperties;

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(dynamicTableNameInnerInterceptor());
        return interceptor;
    }

    private DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor() {
        DynamicTableNameInnerInterceptor innerInterceptor = new DynamicTableNameInnerInterceptor();
        innerInterceptor.setTableNameHandler((sql, tableName) -> {
            String newTableName = tableName;
            // 配置了学校名并且当前查询的表名在指定配置中,则添加表名前缀
            if (StringUtils.hasLength(schoolProperties.getName())
                    && schoolProperties.getDynamicTables().contains(tableName)) {
                newTableName = schoolProperties.getName() + "_" + tableName;
            }
            return newTableName;
        });

        return innerInterceptor;
    }
}

测试

在 test 中创建一个测试类 ScoreServijsceTest :

package cn.fff;

import cn.fff.entity.StudentScore;
import cn.fff.service.ScoreService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

@SpringBootTest
public class ScoreServiceTest {

    @Autowired
    private ScoreService scoreService;

    @Test
    public void testDynameTableName() {
        List<StudentScore> studentScores = scoreService.queryStudentScore();
        studentScores.forEach(e -> System.out.printf("%s %s %d\n", e.getStudentName(), e.getSubjectName(), e.getScore()));
    }
}

当 school.name 为 ustc 时,输出为:

u_aaa Math 89
u_aaa English 81
u_aaa Chinese 32
u_bbb Math 71
u_bbb English 77

当 school.name 为 zju 时,输出为:

z_aaa Math 91
z_aaa English 66
z_aaa Chinese 85
z_bbb Math 48
z_bbb English 59

这样我们就实现了根据配置动态切换操作表名的功能。

到此这篇关于mybatis-plus 实现查询表名动态修改的示例代码的文章就介绍到这了,更多相关mybatis-plus 查询表名动态修改内容请搜索编程China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持China编程(www.chinasem.cn)!

这篇关于mybatis-plus 实现查询表名动态修改的示例代码的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1153790

相关文章

MySQL 中的 JSON 查询案例详解

《MySQL中的JSON查询案例详解》:本文主要介绍MySQL的JSON查询的相关知识,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录mysql 的 jsON 路径格式基本结构路径组件详解特殊语法元素实际示例简单路径复杂路径简写操作符注意MySQL 的 J

pandas中位数填充空值的实现示例

《pandas中位数填充空值的实现示例》中位数填充是一种简单而有效的方法,用于填充数据集中缺失的值,本文就来介绍一下pandas中位数填充空值的实现,具有一定的参考价值,感兴趣的可以了解一下... 目录什么是中位数填充?为什么选择中位数填充?示例数据结果分析完整代码总结在数据分析和机器学习过程中,处理缺失数

Golang HashMap实现原理解析

《GolangHashMap实现原理解析》HashMap是一种基于哈希表实现的键值对存储结构,它通过哈希函数将键映射到数组的索引位置,支持高效的插入、查找和删除操作,:本文主要介绍GolangH... 目录HashMap是一种基于哈希表实现的键值对存储结构,它通过哈希函数将键映射到数组的索引位置,支持

Pandas使用AdaBoost进行分类的实现

《Pandas使用AdaBoost进行分类的实现》Pandas和AdaBoost分类算法,可以高效地进行数据预处理和分类任务,本文主要介绍了Pandas使用AdaBoost进行分类的实现,具有一定的参... 目录什么是 AdaBoost?使用 AdaBoost 的步骤安装必要的库步骤一:数据准备步骤二:模型

Pandas统计每行数据中的空值的方法示例

《Pandas统计每行数据中的空值的方法示例》处理缺失数据(NaN值)是一个非常常见的问题,本文主要介绍了Pandas统计每行数据中的空值的方法示例,具有一定的参考价值,感兴趣的可以了解一下... 目录什么是空值?为什么要统计空值?准备工作创建示例数据统计每行空值数量进一步分析www.chinasem.cn处

使用Pandas进行均值填充的实现

《使用Pandas进行均值填充的实现》缺失数据(NaN值)是一个常见的问题,我们可以通过多种方法来处理缺失数据,其中一种常用的方法是均值填充,本文主要介绍了使用Pandas进行均值填充的实现,感兴趣的... 目录什么是均值填充?为什么选择均值填充?均值填充的步骤实际代码示例总结在数据分析和处理过程中,缺失数

Java对象转换的实现方式汇总

《Java对象转换的实现方式汇总》:本文主要介绍Java对象转换的多种实现方式,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录Java对象转换的多种实现方式1. 手动映射(Manual Mapping)2. Builder模式3. 工具类辅助映

Go语言开发实现查询IP信息的MCP服务器

《Go语言开发实现查询IP信息的MCP服务器》随着MCP的快速普及和广泛应用,MCP服务器也层出不穷,本文将详细介绍如何在Go语言中使用go-mcp库来开发一个查询IP信息的MCP... 目录前言mcp-ip-geo 服务器目录结构说明查询 IP 信息功能实现工具实现工具管理查询单个 IP 信息工具的实现服

利用Python调试串口的示例代码

《利用Python调试串口的示例代码》在嵌入式开发、物联网设备调试过程中,串口通信是最基础的调试手段本文将带你用Python+ttkbootstrap打造一款高颜值、多功能的串口调试助手,需要的可以了... 目录概述:为什么需要专业的串口调试工具项目架构设计1.1 技术栈选型1.2 关键类说明1.3 线程模

SpringBoot基于配置实现短信服务策略的动态切换

《SpringBoot基于配置实现短信服务策略的动态切换》这篇文章主要为大家详细介绍了SpringBoot在接入多个短信服务商(如阿里云、腾讯云、华为云)后,如何根据配置或环境切换使用不同的服务商,需... 目录目标功能示例配置(application.yml)配置类绑定短信发送策略接口示例:阿里云 & 腾