简单实现shardingSphere + MybatisPlus分库分表2025

shardingSphere分库分表简单实现

准备

环境

  • mysql 5.7 +
  • Springboot 3.2 +
  • mybatis-plus 3.5.5
  • druid 1.2.23
  • shardingsphere-jdbc 5.5
  • JDK 21

Pom

xml 复制代码
<dependencies>
    <!-- Spring Boot -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-spring-boot3-starter</artifactId>
        <version>3.5.5</version>
    </dependency>

    <dependency>
        <groupId>com.mysql</groupId>
        <artifactId>mysql-connector-j</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>

    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid-spring-boot-starter</artifactId>
        <version>1.2.23</version>
    </dependency>

    <dependency>
        <groupId>org.apache.shardingsphere</groupId>
        <artifactId>shardingsphere-jdbc</artifactId>
        <version>5.5.0</version>
        <exclusions>
            <exclusion>
                <groupId>org.apache.shardingsphere</groupId>
                <artifactId>shardingsphere-test-util</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>com.alibaba.fastjson2</groupId>
        <artifactId>fastjson2</artifactId>
        <version>2.0.54</version>
    </dependency>
</dependencies>

数据库准备

新建两个库、分别建四张表

sql 复制代码
CREATE DATABASE `order_db_0` /*!40100 DEFAULT CHARACTER SET utf8 */;
CREATE DATABASE `order_db_1` /*!40100 DEFAULT CHARACTER SET utf8 */;

CREATE TABLE `order_0` (
  `order_id` bigint(20) NOT NULL,
  `user_id` bigint(20) NOT NULL,
  `amount` decimal(10,2) NOT NULL,
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`order_id`),
  KEY `idx_user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- 其他四张表结构一致即可

代码部分

配置文件

在resource目录下新建两个文件:

application.yaml

yaml 复制代码
spring:
  main:
    allow-bean-definition-overriding: true
  application:
    name: ls-backend
  datasource:
    driver-class-name: org.apache.shardingsphere.driver.ShardingSphereDriver
    url: jdbc:shardingsphere:classpath:sharding.yaml
  servlet:
    multipart:
      max-file-size: 100MB
      max-request-size: 100MB
server:
  port: 8085
  servlet:
    context-path: /
    encoding:
      force-response: true


#Mybatis扫描
mybatis:
  config-location: classpath:/mybatis-config.xml

mybatis-plus:
  mapper-locations: classpath:/mapper/*Mapper.xml
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

sharding.yaml

yaml 复制代码
dataSources:
  ds0:
    driverClassName: com.mysql.cj.jdbc.Driver
    dataSourceClassName: com.alibaba.druid.pool.DruidDataSource
    url: jdbc:mysql://xxx
    username: test
    password: test
  ds1:
    driverClassName: com.mysql.cj.jdbc.Driver
    dataSourceClassName: com.alibaba.druid.pool.DruidDataSource
    url: jdbc:mysql://yyy
    username: test
    password: test



rules:
  - !SHARDING
    tables:
      order:
        actualDataNodes: ds${0..1}.order_${0..3}
        tableStrategy:
          standard:
            shardingColumn: order_id
            shardingAlgorithmName: order-id-inline
        databaseStrategy:
          standard:
            shardingColumn: user_id
            shardingAlgorithmName: db-inline
    bindingTables:
      - order
    shardingAlgorithms:
      db-inline:
        type: INLINE
        props:
          algorithm-expression: ds${user_id % 2}
      order-id-inline:
        type: INLINE
        props:
          algorithm-expression: order_${order_id % 4}


props:
  sql-show: true

实体类

java 复制代码
@Data
@TableName("`order`") // MyBatis-Plus 表名(与分片表名一致)
public class Order {
    @TableId(type = IdType.ASSIGN_ID) // 手动输入主键(由雪花算法生成)
    private Long orderId; 
    private Long userId;
    private BigDecimal amount;
    private LocalDateTime createTime;
}

Mapper

java 复制代码
@Mapper
public interface OrderMapper extends BaseMapper<Order> {
}

Service

java 复制代码
@Service
@Slf4j
public class OrderService {


    @Autowired
    private OrderMapper orderMapper;

    @Transactional
    public int createOrder(Long userId, BigDecimal amount) {
        SnowflakeIdGenerator generator = new SnowflakeIdGenerator(1, 1);

        Order order = new Order();
        order.setOrderId(generator.nextId()); // 自动生成 BIGINT 类型的雪花 ID
        order.setUserId(userId);
        order.setAmount(amount);
        log.info("即将插入的order: {}", JSON.toJSONString(order));
        // MyBatis-Plus 插入
        return orderMapper.insert(order);
    }

    public List<Order> getOrderById(Long orderId, Long userId) {
        log.info("查询订单,orderId: {}", orderId);
        QueryWrapper<Order> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", userId);
        wrapper.eq("order_id", orderId);
        return orderMapper.selectList(wrapper);
    }
}

雪花算法工具

java 复制代码
public class SnowflakeIdGenerator {
    // 起始时间戳(2024-01-01 00:00:00)
    private static final long TWEPOCH = 1704067200000L;

    // 工作机器 ID(10位,范围:0~1023)
    private final long workerId;

    // 数据中心 ID(10位中的高位,范围:0~1023)
    private final long datacenterId;

    // 序列号(12位,范围:0~4095)
    private long sequence = 0L;

    // 上次生成 ID 的时间戳(毫秒)
    private long lastTimestamp = -1L;

    /**
     * 构造函数(需指定唯一的工作机器 ID 和数据中心 ID)
     * @param workerId 工作机器 ID(0~1023)
     * @param datacenterId 数据中心 ID(0~1023)
     */
    public SnowflakeIdGenerator(long workerId, long datacenterId) {
        // 校验参数范围
        if (workerId > 1023 || workerId < 0) {
            throw new IllegalArgumentException("Worker ID must be between 0 and 1023");
        }
        if (datacenterId > 1023 || datacenterId < 0) {
            throw new IllegalArgumentException("Datacenter ID must be between 0 and 1023");
        }
        this.workerId = workerId;
        this.datacenterId = datacenterId;
    }

    /**
     * 生成下一个 ID
     * @return 64位 BIGINT 类型的雪花算法 ID
     */
    public synchronized long nextId() {
        long timestamp = System.currentTimeMillis();

        // 处理时间戳回拨(可选)
        if (timestamp < lastTimestamp) {
            throw new RuntimeException("Clock moved backwards. Refusing to generate ID");
        }

        // 同一毫秒内生成多个 ID
        if (timestamp == lastTimestamp) {
            sequence = (sequence + 1) & 0xFFF; // 12位掩码(0~4095)
            if (sequence == 0) { // 序列号溢出,等待下一毫秒
                timestamp = waitNextMillis(lastTimestamp);
            }
        } else {
            sequence = 0L; // 新毫秒,序列号重置
        }

        lastTimestamp = timestamp;

        // 计算 ID(按位拼接)
        return ((timestamp - TWEPOCH) << 22) // 时间戳(41位)
                | (datacenterId << 17)       // 数据中心 ID(5位)
                | (workerId << 12)           // 工作机器 ID(5位)
                | sequence;                  // 序列号(12位)
    }

    /**
     * 等待下一毫秒(解决同一毫秒内序列号溢出)
     */
    private long waitNextMillis(long lastTimestamp) {
        long timestamp = System.currentTimeMillis();
        while (timestamp <= lastTimestamp) {
            timestamp = System.currentTimeMillis();
        }
        return timestamp;
    }

    // 测试示例
    public static void main(String[] args) {
        // 示例:工作机器 ID=1,数据中心 ID=1(需根据实际环境调整)
        SnowflakeIdGenerator generator = new SnowflakeIdGenerator(1, 1);
        for (int i = 0; i < 10; i++) {
            System.out.println("Generated ID: " + generator.nextId());
        }
    }
}

实测

创建

bash 复制代码
 INFO 35088 --- [ls-backend] [nio-8085-exec-1] ShardingSphere-SQL                       : Logic SQL: INSERT INTO `order`  ( order_id, user_id, amount )  VALUES (  ?, ?, ?  )
INFO 35088 --- [ls-backend] [nio-8085-exec-1] ShardingSphere-SQL                       : Actual SQL: ds1 ::: INSERT INTO `order_0`  ( order_id, user_id, amount )  VALUES (?, ?, ?) ::: [191145194425552896, 987654321095, 8]

查询

bash 复制代码
INFO 35088 --- [ls-backend] [nio-8085-exec-3] ShardingSphere-SQL                       : Logic SQL: SELECT  order_id,user_id,amount,create_time  FROM `order`      WHERE  (user_id = ? AND order_id = ?)
INFO 35088 --- [ls-backend] [nio-8085-exec-3] ShardingSphere-SQL                       : Actual SQL: ds1 ::: SELECT  order_id,user_id,amount,create_time  FROM `order_0`      WHERE  (user_id = ? AND order_id = ?) ::: [987654321095, 191145194425552896]
相关推荐
不剪发的Tony老师5 分钟前
CloudDM:一站式数据库开发管理工具
数据库
望获linux42 分钟前
【实时Linux实战系列】Linux 内核的实时组调度(Real-Time Group Scheduling)
java·linux·服务器·前端·数据库·人工智能·深度学习
云宏信息44 分钟前
【深度解析】VMware替代的关键一环:云宏ROW快照如何实现高频业务下的“无感”数据保护?
服务器·网络·数据库·架构·云计算·快照
Never_Satisfied1 小时前
在 JavaScript 中,删除数组中内容为xxx的元素
java·前端·javascript
MC丶科1 小时前
【SpringBoot常见报错与解决方案】端口被占用?Spring Boot 修改端口号的 3 种方法,第 3 种 90% 的人不知道!
java·linux·spring boot
怪兽20141 小时前
Redis常见性能问题和解决方案
java·数据库·redis·面试
zz-zjx1 小时前
JVM 内存结构与 GC 机制详解( 实战优化版)
java·jvm·tomcat
nvvas1 小时前
Android Studio JAVA开发按钮跳转功能
android·java·android studio
计算机学长felix1 小时前
基于SpringBoot的“中学信息技术课程教学网站”的设计与实现(源码+数据库+文档+PPT)_2025-10-17
数据库·spring boot·后端
CV工程师丁Sir1 小时前
Rokid设备连接全解析:蓝牙与Wi-Fi通信源码深度剖析
java