mybatis-plus分表实现案例(附示例代码)

2025-12-09 20:50

本文主要是介绍mybatis-plus分表实现案例(附示例代码),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《mybatis-plus分表实现案例(附示例代码)》MyBatis-Plus是一个MyBatis的增强工具,在MyBatis的基础上只做增强不做改变,为简化开发、提高效率而生,:本文主要介绍my...

文档说明

基于springboot框架下mybatis-plus 3.5.5的分表案例和分表实现思路

数据库水平分表思路

1. 为什么要水平分表

•单表数据量过大(千万/亿级):索引膨胀、查询慢、写入压力大
•单机存储瓶颈:一张表的数据撑爆单库存储
•高并发读写:热点表(如订单表、日志表)写入成为瓶颈

2. 核心设计要点

① 确定分片键(Sharding Key)

•分表路由的依据
•要保证每次数据操作都能带上分片键
•常见分片键:user_id、zone_code、tenant_id、时间字段

② 选择分片规则

•范围分表
按时间区间(如 order_202501、order_202502)
   ✅ 适合日志、订单等时间序列数据
   ❌ 跨区间查询不方便

•哈希分表
对分片键取模(如 user_id % 8 → 8 张表)
   ✅ 分布均匀,避免热点
   ❌ 不方便做范围查询

•混合分表
先按业务维度(库级别),再在库内取模或按时间分表

3.基于数据库水平分表注意事项

1.目前基于mybatis-plus分表方案,只能实现单次查询单表操作,如果涉及到单次查询跨表操作就必须引入三方组件来实现(ps:ShardingSphere )
2.分页或者列表查询基于mybatis-plus组件不支持组件纬度跨片查询,此时只能从业务或者分片规则上做调整,比如以年份作为分片条件,列表查询强制要求用户选择时间再进行查询
3.库表必须预先创建好,预先规划好数据量
4.在触发分表操作前必须能拿到分片条件

示例代码

测试表

-- ----------------------------
-- 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 DEFAULChina编程T 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;

-- ----------------------------
-- Table structure for user_3
-- ----------------------------
DROP TABLE IF EXISTS `user_3`;
CREATE TABLE `user_3`  (
  `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_FChina编程ORMAT = Dynamic;



pom依赖

        <dependency>
            <artifactId>gpmscloud-framework-mybatis-commxJNhRtTUpyon</artifactId>
            <groupId>com.bosssoft.gpmscloud</groupId>
            <version>${gpmscloud.version}</version>
        </dependency>

properties配置

spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://192.168.xxx.xxx:xxxxx/gpx_basic?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&serverTimezone=GMT%2B8&useSSL=false&autoReconnect=true
spring.datasource.username=xxx
spring.datasource.password=xxx

spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.druid.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.druid.url=jdbc:mysql://192.168.xxx.xxx:xxxxx/gpx_basic?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&serverTimezone=GMT%2B8&useSSL=false&autoReconnect=true
spring.datasource.druid.username=xxx
spring.datasource.druid.password=xxx

*mybatisplus分表实现类

@Configuration
public class MybatisPlusBasicPlatformConfig {

    @Bean
    public MybatisPlusInterceptor multipleTablesBasicPlatformPlusInterceptor() {
        MybphpatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor = new DynamicTableNameInnerInterceptor();
        dynamicTableNameInnerInterceptor.setTableNameHandler((sql, tableName) -> {
            if (ThreadContextHandler.getThreadLocal().containsKey("tableType")) {
                String tableType = (String) ThreadContextHandler.getThreadLocal().get("tableType");
                return tableName + "_" + tableType;
            } else {
                throw new RuntimeException("未设置分表配置");
            }
        });
        interceptor.addInnerInterceptor(dynamicTableNameInnerInterceptor);
        return interceptor;
    }
}

验证代码

@Data
@Accessors(chain = true)
@TableName(value = "user")
public class User {

    private Long id;
    private String name;
    private Integer age;
    private String email;
}

public interface UserMapper extends BaseMapper<User> {

    User test();

    User test2();
}

<?xml version="1.0" encoding=js"UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.bosssoft.gpmscloud.framework.test.mapper.UserMapper">

    <resultMap type="com.bosssoft.gpmscloud.framework.test.model.po.User" id="UserMapper">
        <result property="id" column="id" jdbcType="INTEGER"/>
        <result property="name" column="resource_id" jdbcType="VARCHAR"/>
        <result property="age" column="white_list" jdbcType="INTEGER"/>
        <result property="email" column="black_list" jdbcType="VARCHAR"/>
    </resultMap>

    <select id="test" resultMap="UserMapper" parameterType="Java.lang.String">
        select id, name, age, email from user
    </select>

    <select id="test2" resultMap="UserMapper" parameterType="java.lang.String">
        select u1.id, u2.name, u2.age, u2.email from user u1
        left join user u2 on u1.user_id = u2.user_id
    </select>


</mapper>


@RestController
@Slf4j
@RequestMapping("/test/multipleTables")
public class MultipleTablesController {

    @Resource
    private UserMapper userMapper;

    /**
     * 验证自动生成库表
     */
    @ApiOperation("test")
    @GetMapping("/test")
    public Result<Boolean> testQuery() {
        ThreadContextHandler.getThreadLocal().put("tableType", "1");
        userMapper.selectList(null);

        ThreadContextHandler.getThreadLocal().put("tableType", "2");
        User user = new User();
        user.setId(1L);
        user.setName("Name");
        user.setAge(1);
        user.setEmail("EMAIL");
        userMapper.insert(user);

        ThreadContextHandler.getThreadLocal().put("tableType", "2");
        userMapper.deleteById(1L);

        ThreadContextHandler.getThreadLocal().put("tableType", "3");
        userMapper.selectList(null);
        return Result.ok(true);
    }

    /**
     * 验证单表和多表自定义xml操作
     */
    @ApiOperation("testXml")
    @GetMapping("/testXml")
    public Result<Boolean> testXml() {
        ThreadContextHandler.getThreadLocal().put("tableType", "2");
        userMapper.test();
        userMapper.test2();
        return Result.ok(true);
    }
}

验证截图

验证mybatisplus内置构建SQL 动态分表

mybatis-plus分表实现案例(附示例代码)

验证xml SQL 动态分表

mybatis-plus分表实现案例(附示例代码)

业务分库分表实现(mybatis-plus)

1.基于上下文内tableType数据进行分表读写,这里需要注意Configuration类命名最好带上服务名,MybatisPlusInterceptor类也是,这样主要是为了避免bean名称冲突
2.业务可以通过上下文参数进行分表参数传递

@Configuration
public class MybatisPlusBasicPlatformConfig {

    @Bean
    public MybatisPlusInterceptor multipleTablesBasicPlatformPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor = new DynamicTableNameInnerInterceptor();
        dynamicTableNameInnerInterceptor.setTableNameHandler((sql, tableName) -> {
            if (ThreadContextHandler.getThreadLocal().containsKey("tableType")) {
                String tableType = (String) ThreadContextHandler.getThreadLocal().get("tableType");
                return tableName + "_" + tableType;
            } else {
                throw new RuntimeException("未设置分表配置");
            }
        });
        interceptor.addInnerInterceptor(dynamicTableNameInnerInterceptor);
        return interceptor;
    }
}

总结 

到此这篇关于mybatis-plus分表实现的文章就介绍到这了,更多相关mybatis-plus分表实现内容请搜索编程China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持China编程(www.chinasem.cn)!

这篇关于mybatis-plus分表实现案例(附示例代码)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1156399

相关文章

mysql_mcp_server部署及应用实践案例

《mysql_mcp_server部署及应用实践案例》文章介绍了在CentOS7.5环境下部署MySQL_mcp_server的步骤,包括服务安装、配置和启动,还提供了一个基于Dify工作流的应用案例... 目录mysql_mcp_server部署及应用案例1. 服务安装1.1. 下载源码1.2. 创建独立

使用Redis实现会话管理的示例代码

《使用Redis实现会话管理的示例代码》文章介绍了如何使用Redis实现会话管理,包括会话的创建、读取、更新和删除操作,通过设置会话超时时间并重置,可以确保会话在用户持续活动期间不会过期,此外,展示了... 目录1. 会话管理的基本概念2. 使用Redis实现会话管理2.1 引入依赖2.2 会话管理基本操作

C#高效实现在Word文档中自动化创建图表的可视化方案

《C#高效实现在Word文档中自动化创建图表的可视化方案》本文将深入探讨如何利用C#,结合一款功能强大的第三方库,实现在Word文档中自动化创建图表,为你的数据呈现和报告生成提供一套实用且高效的解决方... 目录Word文档图表自动化:为什么选择C#?从零开始:C#实现Word文档图表的基本步骤深度优化:C

Mybatis的mapper文件中#和$的区别示例解析

《Mybatis的mapper文件中#和$的区别示例解析》MyBatis的mapper文件中,#{}和${}是两种参数占位符,核心差异在于参数解析方式、SQL注入风险、适用场景,以下从底层原理、使用场... 目录MyBATis 中 mapper 文件里 #{} 与 ${} 的核心区别一、核心区别对比表二、底

Nginx服务器部署详细代码实例

《Nginx服务器部署详细代码实例》Nginx是一个高性能的HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务,:本文主要介绍Nginx服务器部署的相关资料,文中通过代码... 目录Nginx 服务器SSL/TLS 配置动态脚本反向代理总结Nginx 服务器Nginx是一个‌高性

SpringBoot整合AOP及使用案例实战

《SpringBoot整合AOP及使用案例实战》本文详细介绍了SpringAOP中的切入点表达式,重点讲解了execution表达式的语法和用法,通过案例实战,展示了AOP的基本使用、结合自定义注解以... 目录一、 引入依赖二、切入点表达式详解三、案例实战1. AOP基本使用2. AOP结合自定义注解3.

nginx跨域访问配置的几种方法实现

《nginx跨域访问配置的几种方法实现》本文详细介绍了Nginx跨域配置方法,包括基本配置、只允许指定域名、携带Cookie的跨域、动态设置允许的Origin、支持不同路径的跨域控制、静态资源跨域以及... 目录一、基本跨域配置二、只允许指定域名跨域三、完整示例四、配置后重载 nginx五、注意事项六、支持

Qt实现对Word网页的读取功能

《Qt实现对Word网页的读取功能》文章介绍了几种在Qt中实现Word文档(.docx/.doc)读写功能的方法,包括基于QAxObject的COM接口调用、DOCX模板替换及跨平台解决方案,重点讨论... 目录1. 核心实现方式2. 基于QAxObject的COM接口调用(Windows专用)2.1 环境

MySQL查看表的历史SQL的几种实现方法

《MySQL查看表的历史SQL的几种实现方法》:本文主要介绍多种查看MySQL表历史SQL的方法,包括通用查询日志、慢查询日志、performance_schema、binlog、第三方工具等,并... 目录mysql 查看某张表的历史SQL1.查看MySQL通用查询日志(需提前开启)2.查看慢查询日志3.

Java实现字符串大小写转换的常用方法

《Java实现字符串大小写转换的常用方法》在Java中,字符串大小写转换是文本处理的核心操作之一,Java提供了多种灵活的方式来实现大小写转换,适用于不同场景和需求,本文将全面解析大小写转换的各种方法... 目录前言核心转换方法1.String类的基础方法2. 考虑区域设置的转换3. 字符级别的转换高级转换