Mybatis-Plus动态表名插件实现数据库分表查询

简介: Mybatis-Plus动态表名插件实现数据库分表查询

Mybatis-Plus中提供了各种插件,乐观锁、多租户、动态表名。。。。今天来研究一下基于动态表名插件实现分表的案例


环境准备


数据库建三张表测试

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for user_0
-- ----------------------------
DROP TABLE IF EXISTS `user_0`;
CREATE TABLE `user_0`  (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `age` int(2) NULL DEFAULT NULL,
  `email` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Table structure for user_1
-- ----------------------------
DROP TABLE IF EXISTS `user_1`;
CREATE TABLE `user_1`  (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `age` int(2) NULL DEFAULT NULL,
  `email` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Table structure for user_2
-- ----------------------------
DROP TABLE IF EXISTS `user_2`;
CREATE TABLE `user_2`  (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `age` int(2) NULL DEFAULT NULL,
  `email` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;


pom依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.5.2</version>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
    </dependency>
</dependencies>


yml

server:
  port: 8099
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/my_user?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&serverTimezone=Asia/Shanghai
    username: root
    password: root
    #取模分表 格式 表名&表总数量(多个,分隔)。这里随便怎么定义和解析规则对应即可
    modTables: user&3
# Logger Config
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl


请求参数传递辅助类,就是根据什么去分表,这里是根据id

public class RequestDataHelper {
    /**
     * 请求参数存取
     */
    private static final ThreadLocal<Long> REQUEST_DATA = new ThreadLocal<>();
    /**
     * 设置请求参数
     *
     * @param requestData 请求参数 Long
     */
    public static void setRequestData(Long requestData) {
        REQUEST_DATA.set(requestData);
    }
    /**
     * 获取请求参数
     *
     * @param param 请求参数
     * @return 请求参数 MAP 对象
     */
    public static <T> T getRequestData(String param) {
        Long id = getRequestData();
        if (null != id) {
            return (T) id;
        }
        return null;
    }
    /**
     * 获取请求参数
     *
     * @return 请求参数 MAP 对象
     */
    public static Long getRequestData() {
        return REQUEST_DATA.get();
    }
}


注入插件,并且程序初始化时解析分表配置

@Configuration
@MapperScan("com.sample.mapper") //和你包名一致,别问我你的怎么报错了
public class MybatisPlusConfig {
    private static String modTables;
    private static Map<String, Integer> tableMap = new HashMap<>(16);
    @Value("${spring.datasource.modTables:null}")
    public void setModTables(String modTables) {
        MybatisPlusConfig.modTables = modTables;
    }
    @PostConstruct
    public void init() throws Exception {
        String[] split = modTables.split(",");
        for (String s : split) {
            String[] split1 = s.split("&");
            if (split1.length < 2) {
                throw new RuntimeException("分表配置错误");
            }
            MybatisPlusConfig.tableMap.put(split1[0], Integer.valueOf(split1[1]));
        }
    }
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor = new DynamicTableNameInnerInterceptor();
        dynamicTableNameInnerInterceptor.setTableNameHandler((sql, tableName) -> {
            Integer integer = tableMap.get(tableName);
            if (integer != null) {
                // 获取参数方法
                Long id = RequestDataHelper.getRequestData();
                if(id == null){
                    throw new RuntimeException("未设置分表配置");
                }
                long l = Math.floorMod(id, Long.parseLong(integer.toString()));
                return tableName + "_" + l;
            }
            return tableName;
        });
        interceptor.addInnerInterceptor(dynamicTableNameInnerInterceptor);
        // 3.4.3.2 作废该方式
        // dynamicTableNameInnerInterceptor.setTableNameHandlerMap(map);
        return interceptor;
    }
}


实体类

@Data
@Accessors(chain = true)
@TableName(value = "user")
public class User {
    private Long id;
    private String name;
    private Integer age;
    private String email;
}


mapper

/**
 * @author: yh
 * @Description: 支持不需要 UserMapper.xml 这个模块演示内置 CRUD 咱们就不要 XML 部分了
 * @date: 2022/6/6 12:24
 */
public interface UserMapper extends BaseMapper<User> {
}


测试


现在就可以测试啦,编写一个测试方法

@Resource
    private UserMapper userMapper;
    /**
     * 分表测试
     * 执行后观察打印sql
     * @author yh
     * @date 2022/6/6
     */
    @Test
    public void test1() {
        RequestDataHelper.setRequestData(1L);
        userMapper.selectList(null);
        RequestDataHelper.setRequestData(2L);
        userMapper.selectList(null);
        RequestDataHelper.setRequestData(3L);
         userMapper.selectList(null);
        RequestDataHelper.setRequestData(4L);
        userMapper.selectList(null);
    }


结果:

1673457441221.jpg

不同的业务id按照user_ 加 id取模,组成表名查询。这里的分表规则随便怎么定义 时间、id、字符串hash都可以。


完整代码已上传Gitee Spring整合常用组件

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
相关文章
|
Java 数据库连接 数据库
Spring boot 使用mybatis generator 自动生成代码插件
本文介绍了在Spring Boot项目中使用MyBatis Generator插件自动生成代码的详细步骤。首先创建一个新的Spring Boot项目,接着引入MyBatis Generator插件并配置`pom.xml`文件。然后删除默认的`application.properties`文件,创建`application.yml`进行相关配置,如设置Mapper路径和实体类包名。重点在于配置`generatorConfig.xml`文件,包括数据库驱动、连接信息、生成模型、映射文件及DAO的包名和位置。最后通过IDE配置运行插件生成代码,并在主类添加`@MapperScan`注解完成整合
1784 1
Spring boot 使用mybatis generator 自动生成代码插件
|
SQL Java 数据安全/隐私保护
发现问题:Mybatis-plus的分页总数为0,分页功能失效,以及多租户插件的使用。
总的来说,使用 Mybatis-plus 确实可以极大地方便我们的开发,但也需要我们理解其工作原理,掌握如何合适地使用各种插件。分页插件和多租户插件是其中典型,它们的运用可以让我们的代码更为简洁、高效,理解和掌握好它们的用法对我们的开发过程有着极其重要的意义。
1164 15
|
人工智能 JavaScript 关系型数据库
【02】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-ui设计图figmaUI设计准备-figma汉化插件-mysql数据库设计-优雅草卓伊凡商业项目实战
【02】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-ui设计图figmaUI设计准备-figma汉化插件-mysql数据库设计-优雅草卓伊凡商业项目实战
664 14
【02】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-ui设计图figmaUI设计准备-figma汉化插件-mysql数据库设计-优雅草卓伊凡商业项目实战
|
SQL Java 数据库连接
深入 MyBatis-Plus 插件:解锁高级数据库功能
Mybatis-Plus 提供了丰富的插件机制,这些插件可以帮助开发者更方便地扩展 Mybatis 的功能,提升开发效率、优化性能和实现一些常用的功能。
2175 26
深入 MyBatis-Plus 插件:解锁高级数据库功能
|
缓存 NoSQL 关系型数据库
WordPress数据库查询缓存插件
这款插件通过将MySQL查询结果缓存至文件、Redis或Memcached,加速页面加载。它专为未登录用户优化,支持跨页面缓存,不影响其他功能,且可与其他缓存插件兼容。相比传统页面缓存,它仅缓存数据库查询结果,保留动态功能如阅读量更新。提供三种缓存方式选择,有效提升网站性能。
417 1
|
XML SQL Java
十二、MyBatis分页插件
十二、MyBatis分页插件
546 17
|
SQL Java 数据库连接
【MyBatisPlus·最新教程】包含多个改造案例,常用注解、条件构造器、代码生成、静态工具、类型处理器、分页插件、自动填充字段
MyBatis-Plus是一个MyBatis的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。本文讲解了最新版MP的使用教程,包含多个改造案例,常用注解、条件构造器、代码生成、静态工具、类型处理器、分页插件、自动填充字段等核心功能。
2833 6
【MyBatisPlus·最新教程】包含多个改造案例,常用注解、条件构造器、代码生成、静态工具、类型处理器、分页插件、自动填充字段
|
SQL 缓存 Java
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
本文详细介绍了MyBatis的各种常见用法MyBatis多级缓存、逆向工程、分页插件 包括获取参数值和结果的各种情况、自定义映射resultMap、动态SQL
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
|
SQL XML Java
六、MyBatis特殊的SQL:模糊查询、动态设置表名、校验名称唯一性
六、MyBatis特殊的SQL:模糊查询、动态设置表名、校验名称唯一性
589 0
|
关系型数据库 MySQL 数据库
使用Docker部署的MySQL数据库如何设置忽略表名大小写?
【10月更文挑战第1天】使用Docker部署的MySQL数据库如何设置忽略表名大小写?
2311 1