当前位置: 代码网 > it编程>编程语言>Java > mybatis-plus 实现查询表名动态修改的示例代码

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

2025年03月17日 Java 我要评论
通过 mybatis-plus 实现表名的动态替换,即通过配置或入参动态选择不同的表。下面通过一个例子来说明该需求: 我们需要为学校开发一个成绩管理系统,需要建立三张表: 学生表、科目表和成绩表,表的

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

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

对应的建表语句如下:

-- 学科表
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 图如下所示。

不同学校的建表语句不同,对于 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 ustc_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 添加如下配置:

school:
  name: ustc
  dynamic-tables:
    - student
    - 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;
import 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 中创建一个测试类 scoreservicetest :

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 查询表名动态修改内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com