这里写目录标题
1前言
3.4.3.2 作废setTableNameHandlerMap方式,这里不做赘述
// 3.4.3.2 作废该方式
// dynamicTableNameInnerInterceptor.setTableNameHandlerMap(map);
官网地址https://baomidou.com/plugins/dynamic-table-name/
官网案例源码https://gitee.com/baomidou/mybatis-plus-samples/tree/master/mybatis-plus-sample-dynamic-tablename
官网给的案例不是非常适合项目中处理,这里简单介绍一下我自己的想法
2 增加maven依赖
<!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-boot-starter -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.6</version>
</dependency>
3 核心就下面的3个文件
通过本地线程来存储要操作的表名字,等到sql要执行的时候再替换为需要执行的表名字来实现动态表名
TableDto
package cn.fox.mydemo.domain.dto;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class TableDto {
/**
* 表名字前缀
*/
private String tableNamePrefix;
/**
* 表名字全称
*/
private String tableName;
}
TableStrThreadLocal 本地线程
package cn.fox.mydemo.domain.dto;
import com.baomidou.mybatisplus.annotation.TableName;
/**
* 表名线程变量
*/
public class TableStrThreadLocal {
private static final ThreadLocal<TableDto> TABLE_STR_TL = new ThreadLocal<>();
/**
* 设置
* @param clazz class
* @param tableNameSuffix 表名字后缀
*/
public static void set(Class<?> clazz, String tableNameSuffix) {
TableDto tableDto = new TableDto();
TableName tableNamePrefix = clazz.getAnnotation(TableName.class);
tableDto.setTableNamePrefix(tableNamePrefix.value());
tableDto.setTableName(tableNamePrefix.value() + tableNameSuffix);
TABLE_STR_TL.set(tableDto);
}
/**
* 获取
* @return String
*/
public static TableDto get(){
if(TABLE_STR_TL.get() == null){
TABLE_STR_TL.set(new TableDto());
}
return TABLE_STR_TL.get();
}
/**
* 删除
*/
public static void remove() {
TABLE_STR_TL.remove();
}
}
Configuration
package cn.fox.mydemo.config;
import cn.fox.mydemo.domain.dto.TableDto;
import cn.fox.mydemo.domain.dto.TableStrThreadLocal;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.DynamicTableNameInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration(proxyBeanMethods = false)
public class MybatisAutoConfiguration implements WebMvcConfigurer {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 分页插件, 对于单一数据库类型来说,都建议配置该值,避免每次分页都去抓取数据库类型
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor = new DynamicTableNameInnerInterceptor();
dynamicTableNameInnerInterceptor.setTableNameHandler((sql, originalTableName) -> {
TableDto tableDto = TableStrThreadLocal.get();
// 如果缓存里面的表名字前缀和固定值相等,就取缓存里面的表名字全称
if("user_".equals(tableDto.getTableNamePrefix())){
return tableDto.getTableName();
}
// 没有匹配到就取原来的表名字
return originalTableName;
});
// 3.4.3.2 作废该方式
// dynamicTableNameInnerInterceptor.setTableNameHandlerMap(map);
interceptor.addInnerInterceptor(dynamicTableNameInnerInterceptor);
return interceptor;
}
}
4 测试
新建两张表,加两条数据
CREATE TABLE `user_1` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键id',
`name` varchar(255) DEFAULT NULL COMMENT '名字',
`age` int(11) DEFAULT NULL COMMENT '年龄',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `user_2` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键id',
`name` varchar(255) DEFAULT NULL COMMENT '名字',
`age` int(11) DEFAULT NULL COMMENT '年龄',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO `my_test`.`user_1` (`id`, `name`, `age`) VALUES (1, '用户1', 18);
INSERT INTO `my_test`.`user_1` (`id`, `name`, `age`) VALUES (1, '用户2', 35);
user实体
package cn.fox.mydemo.domain.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Getter;
import lombok.Setter;
import java.io.Serializable;
@Getter
@Setter
@TableName("user_")
public class User implements Serializable {
private static final long serialVersionUID = 132777406752307410L;
/**
* 主键id
*/
private Integer id;
/**
* 名字
*/
private String name;
/**
* 年龄
*/
private Integer age;
}
mapper
package cn.fox.mydemo.mapper;
import cn.fox.mydemo.domain.entity.User;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface UserMapper extends BaseMapper<User> {
}
IUserService
package cn.fox.mydemo.service;
import cn.fox.mydemo.domain.entity.User;
import com.baomidou.mybatisplus.extension.service.IService;
public interface IUserService extends IService<User> {
}
UserServiceImpl
package cn.fox.mydemo.service.impl;
import cn.fox.mydemo.domain.entity.User;
import cn.fox.mydemo.mapper.UserMapper;
import cn.fox.mydemo.service.IUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
}
测试
package cn.fox.mydemo;
import cn.fox.mydemo.domain.dto.TableStrThreadLocal;
import cn.fox.mydemo.domain.entity.User;
import cn.fox.mydemo.service.IUserService;
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 TableDemo {
@Autowired
private IUserService userService;
@Test
public void test() {
TableStrThreadLocal.set(User.class, "1");
List<User> list1 = userService.list();
System.out.println(list1);
TableStrThreadLocal.set(User.class, "2");
List<User> list2 = userService.list();
System.out.println(list2);
}
}
TableStrThreadLocal.set(User.class, “1”);
第一个参数是实体class,第二个参数是要动态调用的表名字后缀,在mybatisplsh调用之前设置一下就行。