mybatis-plus?實(shí)現(xiàn)查詢表名動(dòng)態(tài)修改的示例代碼
通過 mybatis-plus 實(shí)現(xiàn)表名的動(dòng)態(tài)替換,即通過配置或入?yún)?dòng)態(tài)選擇不同的表。
下面通過一個(gè)例子來說明該需求: 我們需要為學(xué)校開發(fā)一個(gè)成績管理系統(tǒng),需要建立三張表: 學(xué)生表、科目表和成績表,表的 ER 圖如下所示。

對應(yīng)的建表語句如下:
-- 學(xué)科表 drop table if exists subject; create table subject(id int primary key , name varchar(64)); -- 學(xué)生表 drop table if exists student; create table student (id int primary key , name varchar(64)); -- 成績表(學(xué)生-學(xué)科 多對多) drop table if exists score; create table score(id int primary key , student_id int, subject_id int, result int);
根據(jù)三張表級聯(lián)查詢成績的查詢語句為:
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;
現(xiàn)在又來了一個(gè)新需求,我們的這套成績查詢系統(tǒng)需要部署在不同學(xué)校的服務(wù)器上,因?yàn)槊總€(gè)學(xué)校的學(xué)生表和成績表都要同步到教育局的服務(wù)器中,因此需要為這兩個(gè)表添加學(xué)校前綴,ER 圖如下所示。

不同學(xué)校的建表語句不同,對于 USTC 學(xué)校而言,建表語句為:
-- 學(xué)科表 drop table if exists subject; create table subject(id int primary key , name varchar(64)); -- 學(xué)生表 drop table if exists ustc_student; create table ustc_student (id int primary key , name varchar(64)); -- 成績表(學(xué)生-學(xué)科 多對多) drop table if exists ustc_score; create table ustc_score(id int primary key , student_id int, subject_id int, result int);
對于 ZJU 學(xué)校而言,建表語句為:
-- 學(xué)科表 drop table if exists subject; create table subject(id int primary key , name varchar(64)); -- 學(xué)生表 drop table if exists zju_student; create table zju_student (id int primary key , name varchar(64)); -- 成績表(學(xué)生-學(xué)科 多對多) drop table if exists zju_score; create table zju_score(id int primary key , student_id int, subject_id int, result int);
我們的成績查詢系統(tǒng)會(huì)安裝在不同的學(xué)校,并且校名是動(dòng)態(tài)可配的,因此該成績查詢系統(tǒng)需要根據(jù)配置文件動(dòng)態(tài)修改 sql 語句表名的功能。
實(shí)現(xiàn)
源碼地址: https://github.com/foolishflyfox/blog/tree/main/backend-code/mp-dynamic-tablename
數(shù)據(jù)庫初始化
創(chuàng)建程序需要的表:
create database if not exists mp_dynamic_tablename_test;
use mp_dynamic_tablename_test;
-- 學(xué)科表
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');
-- 學(xué)生表
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');
-- 成績表(學(xué)生-學(xué)科 多對多)
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 的表
-- 學(xué)生表
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');
-- 成績表(學(xué)生-學(xué)科 多對多)
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 的表
-- 學(xué)生表
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');
-- 成績表(學(xué)生-學(xué)科 多對多)
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 庫。
配置讀取類
我們先定義一個(gè)配置讀取類,用于獲取動(dòng)態(tài)配置的學(xué)校以及需要?jiǎng)討B(tài)添加學(xué)校前綴的表名。
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 {
/** 學(xué)校名,動(dòng)態(tài)表名會(huì)添加前綴: 學(xué)校名_ */
private String name;
/** 需要?jiǎng)討B(tài)添加前綴的表 */
private Set<String> dynamicTables = new HashSet<>();
}
為 application.yml 添加如下配置:
school:
name: ustc
dynamic-tables:
- student
- score
表示需要為 student 和 score 動(dòng)態(tài)添加前綴 ustc,即查詢 student 表時(shí)會(huì)動(dòng)態(tài)替換為 ustc_student,查詢 score 表時(shí)會(huì)動(dòng)態(tài)替換為 ustc_score。如果 school.name 修改為 zju,則查詢 student 表時(shí)會(huì)動(dòng)態(tài)替換為 zju_student,查詢 score 表時(shí)會(huì)動(dòng)態(tài)替換為 zju_score。
設(shè)置 mybatis-plus 插件
實(shí)體類、mapper、服務(wù)類的創(chuàng)建比較基礎(chǔ),此處略過,可直接查看源碼。動(dòng)態(tài)表面主要通過創(chuàng)建一個(gè) mybatis 插件實(shí)現(xiàn):
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;
// 配置了學(xué)校名并且當(dāng)前查詢的表名在指定配置中,則添加表名前綴
if (StringUtils.hasLength(schoolProperties.getName())
&& schoolProperties.getDynamicTables().contains(tableName)) {
newTableName = schoolProperties.getName() + "_" + tableName;
}
return newTableName;
});
return innerInterceptor;
}
}
測試
在 test 中創(chuàng)建一個(gè)測試類 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()));
}
}
當(dāng) school.name 為 ustc 時(shí),輸出為:
u_aaa Math 89 u_aaa English 81 u_aaa Chinese 32 u_bbb Math 71 u_bbb English 77
當(dāng) school.name 為 zju 時(shí),輸出為:
z_aaa Math 91 z_aaa English 66 z_aaa Chinese 85 z_bbb Math 48 z_bbb English 59
這樣我們就實(shí)現(xiàn)了根據(jù)配置動(dòng)態(tài)切換操作表名的功能。
到此這篇關(guān)于mybatis-plus 實(shí)現(xiàn)查詢表名動(dòng)態(tài)修改的示例代碼的文章就介紹到這了,更多相關(guān)mybatis-plus 查詢表名動(dòng)態(tài)修改內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- mybatis plus動(dòng)態(tài)數(shù)據(jù)源切換及查詢過程淺析
- MybatisPlus實(shí)現(xiàn)分頁查詢和動(dòng)態(tài)SQL查詢的示例代碼
- MyBatis-Plus多表聯(lián)查的實(shí)現(xiàn)方法(動(dòng)態(tài)查詢和靜態(tài)查詢)
- Mybatis-plus動(dòng)態(tài)條件查詢QueryWrapper的使用案例
- MyBatis-Plus多表聯(lián)查(動(dòng)態(tài)查詢)的項(xiàng)目實(shí)踐
- MybatisPlus使用Mybatis的XML的動(dòng)態(tài)SQL的功能實(shí)現(xiàn)多表查詢
- mybatis-plus @select動(dòng)態(tài)查詢方式
相關(guān)文章
Java多線程編程之CountDownLatch同步工具使用實(shí)例
這篇文章主要介紹了Java多線程編程之CountDownLatch同步工具使用實(shí)例,需要的朋友可以參考下2015-05-05
將SpringBoot項(xiàng)目打包成EXE文件的完整教程(多種方式)
在Spring Boot項(xiàng)目中打包是一個(gè)非常重要的環(huán)節(jié),因?yàn)樗鼪Q定了應(yīng)用程序如何部署到生產(chǎn)環(huán)境中,這篇文章主要介紹了將SpringBoot項(xiàng)目打包成EXE文件的完整教程,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2025-10-10
SpringMVC中使用bean來接收form表單提交的參數(shù)時(shí)的注意點(diǎn)
本篇文章主要介紹了SpringMVC中使用bean來接收form表單提交的參數(shù)時(shí)的注意點(diǎn),具有很好的參考價(jià)值。下面跟著小編一起來看下吧2017-05-05
Java利用Spire.Doc實(shí)現(xiàn)RTF轉(zhuǎn)換PDF的高效方案
在企業(yè)級應(yīng)用開發(fā)中,RTF格式雖因其良好的兼容性曾在文檔交換領(lǐng)域占據(jù)一席之地,但隨著移動(dòng)辦公和長期歸檔需求的增加,其跨平臺(tái)顯示不一致、易被篡改的弊端日益凸顯,本文將介紹如何利用Spire.Doc for Java這一強(qiáng)大的類庫實(shí)現(xiàn)將RTF轉(zhuǎn)換為PDF,需要的朋友可以參考下2026-03-03
mybatis 忽略實(shí)體對象的某個(gè)屬性(2種方式)
這篇文章主要介紹了mybatis 忽略實(shí)體對象的某個(gè)屬性方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06
解決java.lang.Error: Unresolved compilation pro
這篇文章主要介紹了解決java.lang.Error: Unresolved compilation problems:問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03
Java注解@Conditional與@Profile的使用區(qū)別
這篇文章主要介紹了Java注解@Conditional與@Profile的使用區(qū)別,@Profile和@Conditional是Spring提供的兩種常用機(jī)制,它們可以根據(jù)不同的條件動(dòng)態(tài)決定某些Bean是否加載,從而實(shí)現(xiàn)環(huán)境隔離、模塊選擇、特性開關(guān)等功能,需要的朋友可以參考下2025-05-05
Idea配置Maven阿里云鏡像加速的實(shí)現(xiàn)
這篇文章主要介紹了Idea配置Maven阿里云鏡像加速的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04
Spring IOC相關(guān)注解運(yùn)用(上篇)
這篇文章主要介紹了Spring?IOC相關(guān)注解的運(yùn)用,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-05-05

