MyBatis-Plus使用动态表名分表查询

动态修改表名的场景通常用于:

  • 分表策略:根据不同的条件(如年份、月份、区域等)来选择查询不同的表。
  • 多租户系统:根据租户的不同,查询不同的表。
  • 历史数据管理:查询历史表的数据时,动态决定表名(例如每年有一个对应的表,table_2021, table_2022 等)。

1. 引入依赖

xml 复制代码
 <dependency>
     <groupId>com.baomidou</groupId>
     <artifactId>mybatis-plus-boot-starter</artifactId>
     <version>3.5.3</version>   
 </dependency>

注意:版本须使用3.5.3以上,否则无法使用DynamicTableNameInnerInterceptor类中的setTableNameHandler方法

2. mybatis-plus配置

java 复制代码
@Configuration
@Slf4j
public class MybatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        // 数据权限
        //mybatisPlusInterceptor.addInnerInterceptor(new DataFilterInterceptor());
        // 乐观锁
        mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        // 防止全表更新与删除
        mybatisPlusInterceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
        //动态表名
        DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor = new DynamicTableNameInnerInterceptor();
        dynamicTableNameInnerInterceptor.setTableNameHandler((sql, tableName) -> { //匿名内部类
            String tenant = TenantContext.TENANT_DATA.get();
            // 如果不为空,使用动态表名。
            if (StringUtils.isNotBlank(tenant) && TenantContext.containsTableName(tableName)) {
                log.info("dynamicTableName -- >tableName={}, tenant={}",tableName, tenant);
                return tableName + "_" + tenant;
            }
            return tableName;
        });
        mybatisPlusInterceptor.addInnerInterceptor(dynamicTableNameInnerInterceptor);
        // 分页插件
        mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return mybatisPlusInterceptor;
    }
}

3. TenantContext 类:租户上下文管理器

java 复制代码
public class TenantContext {

    // 需要替换的动态表名
    public static ThreadLocal<String> TENANT_DATA = new ThreadLocal<>();

    //用于记录哪些表可以使用该动态表名处理器
    private static List<String> tableNames = Arrays.asList("test_user");

    //设置请求线程的租户数据
    public static void setTenantData(String tenant) {
        TENANT_DATA.set(tenant);
    }

    //删除当前请求线程的租户数据
    public static void removeYearData() {
        TENANT_DATA.remove();
    }

    public static Boolean containsTableName(String tableName) {
        if (tableNames.contains(tableName)) {
            return true;
        }
        return false;
    }

}

4. 实体类

java 复制代码
@Data
@TableName("test_user")
public class TestUser implements Serializable {
    private String id;
    private String name;
    private String managerId;
    private String salary;
    private String age;
    private String departId;
    private String remark;
    private String province;
}

5. 具体实现

java 复制代码
@RestController
@Slf4j
public class TestController {

    @Resource
    private ITestUserService testUserService;

    @GetMapping("/selectList")
    public List<TestUser> selectList(@RequestParam String tenant) {
        return testUserService.selectList(tenant);
    }
}

public interface ITestUserService extends IService<TestUser> {

    List<TestUser> selectList(String tenant);
}

@Service
public class TestUserServiceImpl extends ServiceImpl<TestUserMapper, TestUser> implements ITestUserService {

    @Overridejava
    public List<TestUser> selectList(String tenant) {
        TenantContext.setTenantData(tenant);
        Wrapper<TestUser> queryWrapper = new QueryWrapper<>();
        return baseMapper.selectList(queryWrapper);
    }
}
相关推荐
秋月的私语4 小时前
如何快速将当前的c#工程发布成单文件
android·java·c#
天***88964 小时前
使用python写一个应用程序要求实现微软常用vc++功能排查与安装功能
java
代码充电宝5 小时前
LeetCode 算法题【简单】283. 移动零
java·算法·leetcode·职场和发展
MediaTea7 小时前
Python IDE:Spyder
开发语言·ide·python
不枯石8 小时前
Matlab通过GUI实现点云的均值滤波(附最简版)
开发语言·图像处理·算法·计算机视觉·matlab·均值算法
不枯石8 小时前
Matlab通过GUI实现点云的双边(Bilateral)滤波(附最简版)
开发语言·图像处理·算法·计算机视觉·matlab
ccccczy_8 小时前
Spring Security 深度解读:JWT 无状态认证与权限控制实现细节
java·spring security·jwt·authentication·authorization·securityfilterchain·onceperrequestfilter
Lin_Aries_04218 小时前
容器化 Tomcat 应用程序
java·linux·运维·docker·容器·tomcat
sheji34168 小时前
【开题答辩全过程】以 springboot高校社团管理系统的设计与实现为例,包含答辩的问题和答案
java·spring boot·后端