天天看点

Spring Boot demo系列(十三):ShardingSphere + MyBatisPlus 分库分表1 概述2 准备数据库环境3 新建项目4 配置文件5 测试代码生成6 增加雪花id生成器7 测试8 参考源码

1 概述

本文主要讲述了如何使用

ShardingSphere

(其中的

Sharding-JDBC

)和

MyBatisPlus

进行分库分表,具体步骤包括:

  • 准备数据库环境
  • 准备依赖
  • 编写配置文件
  • 测试

2 准备数据库环境

2.1 两库六表

准备好两个库:

  • test0

  • test1

在两个库中分别建立三个字段一样的表:

  • user0

  • user1

  • user2

Spring Boot demo系列(十三):ShardingSphere + MyBatisPlus 分库分表1 概述2 准备数据库环境3 新建项目4 配置文件5 测试代码生成6 增加雪花id生成器7 测试8 参考源码

字段如下:

Spring Boot demo系列(十三):ShardingSphere + MyBatisPlus 分库分表1 概述2 准备数据库环境3 新建项目4 配置文件5 测试代码生成6 增加雪花id生成器7 测试8 参考源码

这样就准备了两个库以及其中的六个表了。

2.2 (可选)

MyBatis Plus Generator

代码生成表

因为

MyBatis Plus Generator

生成的

Controller

等代码默认是按照表名命名的,这样就会生成类似

User0

User0Controller

这样的命名,因此这里创建一个叫

user

的表,仅仅用于代码的生成,里面不会存放任何的数据:

Spring Boot demo系列(十三):ShardingSphere + MyBatisPlus 分库分表1 概述2 准备数据库环境3 新建项目4 配置文件5 测试代码生成6 增加雪花id生成器7 测试8 参考源码

3 新建项目

新建

Spring Boot

项目并引入如下依赖:

  • Druid

  • MyBatis Plus starter

  • MyBaits Plus Generator

  • Velocity core

  • ShardingSphere

  • Yitter

    (一个雪花

    id

    生成器)

Maven

如下:

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.3.1</version>
</dependency>
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>3.5.0</version>
</dependency>
<dependency>
    <groupId>org.apache.velocity</groupId>
    <artifactId>velocity-engine-core</artifactId>
    <version>2.3</version>
</dependency>
<dependency>
    <groupId>org.realityforge.org.jetbrains.annotations</groupId>
    <artifactId>org.jetbrains.annotations</artifactId>
    <version>1.7.0</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.2.6</version>
</dependency>
<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
    <version>4.1.1</version>
</dependency>
<dependency>
    <groupId>com.github.yitter</groupId>
    <artifactId>yitter-idgenerator</artifactId>
    <version>1.0.6</version>
</dependency>
           

Gradle

如下:

implementation 'com.baomidou:mybatis-plus-boot-starter:3.4.3.1'
implementation 'org.apache.velocity:velocity-engine-core:2.3'
implementation 'org.realityforge.org.jetbrains.annotations:org.jetbrains.annotations:1.7.0'
implementation 'com.alibaba:druid:1.2.6'
implementation 'org.apache.shardingsphere:sharding-jdbc-spring-boot-starter:4.1.1'
implementation 'com.github.yitter:yitter-idgenerator:1.0.6'
           

4 配置文件

配置文件可以参考ShardingSphere文档,这里给出一个示例配置:

spring:
  shardingsphere:
    datasource:
      names: test0,test1                                        # 数据源,这里为了方便直接使用库名的名称
      test0:                                                   
        type: com.alibaba.druid.pool.DruidDataSource            # Druid连接池
        url: jdbc:mysql://127.0.0.1:3306/test0                  # 连接test0的url
        username: root
        password: 123456
      test1:
        type: com.alibaba.druid.pool.DruidDataSource            # Druid连接池
        url: jdbc:mysql://127.0.0.1:3306/test1                  # 连接test1的url
        username: root
        password: 123456
    sharding:
      default-database-strategy:                                # 默认分库策略
        inline:  
          sharding-column: age                                  # 表示根据age列进行分库
          algorithm-expression: test$->{age % 2}                # 根据age对2的模进行分库,模为0表示test0库,模为1表示test1库
      tables:
        user:
          actual-data-nodes: test$->{0..1}.user$->{0..2}        # 表的名字,test$->{0..1}可以表示test0、test1两个库
                                                                # user$->{0..2}表示user0、user1、user2三个库
          table-strategy:                                       # 分表策略
            inline:
              sharding-column: id                               # 根据哪一列进行分表,id表示根据列名为"id"的列分表
              algorithm-expression: user$->{id%3}               # 分表规则为id对3取模,id%3为0表示分到user0表
                                                                # id%3为1表示分到user1表,id%3为2表示分到user2表
    props:
      sql:
        show:
          true                                                  # 打印sql
           

这里使用自动取模分片策略,

ShardingShphere

内置了如下分片算法:

  • 自动分片算法:取模分片、哈希取模分片、基于分片容量的范围分片、基于分片边界的范围分片、自动时间段分片
  • 标准分片算法:行表达式分片、时间范围分片
  • 复合行表达式分片
  • Hint

    行表达式分片

如果不能满足需要还可以自定义分片算法,具体请看官方文档。

5 测试代码生成

使用

MyBaits Plus Generator

生成相应代码,具体使用可以参考笔者之前的文章,这里直接放上生成类的代码:

import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.*;

public class MyBatisPlusGenerator {
    public static void main(String[] args) {
        DataSourceConfig dataSourceConfig = new DataSourceConfig.Builder("jdbc:mysql://localhost:3306/test0", "root", "123456").build();
        String projectPath = System.getProperty("user.dir");
        StrategyConfig strategyConfig = new StrategyConfig.Builder().addInclude("user").build();
        GlobalConfig globalConfig = new GlobalConfig.Builder().outputDir(projectPath + "/src/main/java").openDir(false).build();
        PackageConfig packageConfig = new PackageConfig.Builder().moduleName("user").parent("com.example.demo").serviceImpl("service").build();
        new AutoGenerator(dataSourceConfig).global(globalConfig).packageInfo(packageConfig).strategy(strategyConfig).execute();
    }
}
           

UserController

类修改如下:

@RestController
@RequestMapping("/user")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class UserController {
    private final Random random = new Random();
    private final UserServiceImpl service;
    @GetMapping("/select")
    public List<User> select(){
        return service.list();
    }

    @GetMapping("/insert")
    public boolean insert(){
        return service.save(User.builder().age(random.nextInt(80)+20).name("test name").email("[email protected]").build());
    }
}
           

6 增加雪花

id

生成器

首先修改

User

类,增加一个

@Builder

注解,同时修改

id

的生成策略,使用

IdType.ASSIGN_ID

@Builder
public class User implements Serializable {
    @TableId(type = IdType.ASSIGN_ID)
    private Long id;
    //...
}
           

新建

id

生成器类:

import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
import com.github.yitter.contract.IdGeneratorOptions;
import com.github.yitter.idgen.YitIdHelper;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

@Component
public class IdGenerator implements IdentifierGenerator {
    final IdGeneratorOptions options = new IdGeneratorOptions((short) 1);

    @PostConstruct
    public void init() {
        YitIdHelper.setIdGenerator(options);
    }

    @Override
    public Long nextId(Object entity) {
        return YitIdHelper.nextId();
    }
}
           

这样生成

id

的时候,就会自动调用

nextId()

方法,其中的

id

生成器可以根据需要进行替换,换成其他雪花

id

生成器或分布式

id

生成器。

配置的时候可以参考MyBaits Plus 自定义ID生成器文档。

7 测试

先随机插入三条数据,刷新三次如下页面:

localhost:8080/test/user/insert
           
Spring Boot demo系列(十三):ShardingSphere + MyBatisPlus 分库分表1 概述2 准备数据库环境3 新建项目4 配置文件5 测试代码生成6 增加雪花id生成器7 测试8 参考源码

可以看到执行了三次插入操作,插入的三个表分别是:

  • test0.user2

  • test0.user0

  • test0.user2

因为这里测试的时候年龄都恰好是偶数,都插入到了

test0

表。

查看数据:

http://localhost:8080/user/select
           
Spring Boot demo系列(十三):ShardingSphere + MyBatisPlus 分库分表1 概述2 准备数据库环境3 新建项目4 配置文件5 测试代码生成6 增加雪花id生成器7 测试8 参考源码

日志输出如下:

Spring Boot demo系列(十三):ShardingSphere + MyBatisPlus 分库分表1 概述2 准备数据库环境3 新建项目4 配置文件5 测试代码生成6 增加雪花id生成器7 测试8 参考源码

表示这是对六个表查询的结果,并将最后的结果进行聚合返回。

8 参考源码

Java

版:

  • Github
  • 码云
  • CODE.CHINA

Kotlin

版:

  • Github
  • 码云
  • CODE.CHINA

继续阅读