1 概述
本文次要讲述了如何应用 ShardingSphere
(其中的Sharding-JDBC
)和MyBatisPlus
进行分库分表,具体步骤包含:
- 筹备数据库环境
- 筹备依赖
- 编写配置文件
- 测试
2 筹备数据库环境
2.1 两库六表
筹备好两个库:
test0
test1
在两个库中别离建设三个字段一样的表:
user0
user1
user2
字段如下:
这样就筹备了两个库以及其中的六个表了。
2.2(可选)MyBatis Plus Generator
代码生成表
因为 MyBatis Plus Generator
生成的 Controller
等代码默认是依照表名命名的,这样就会生成相似 User0
、User0Controller
这样的命名,因而这里创立一个叫 user
的表,仅仅用于代码的生成,外面不会寄存任何的数据:
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:
datasource:
url: jdbc:mysql://127.0.0.1:3306/test # spring 数据源
username: root # 用户名
password: 123456 # 明码
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("test@test.com").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
能够看到执行了三次插入操作,插入的三个表别离是:
test0.user2
test0.user0
test0.user2
因为这里测试的时候年龄都恰好是偶数,都插入到了 test0
表。
查看数据:
http://localhost:8080/user/select
日志输入如下:
示意这是对六个表查问的后果,并将最初的后果进行聚合返回。
8 参考源码
Java
版:
- Github
- 码云
- CODE.CHINA
Kotlin
版:
- Github
- 码云
- CODE.CHINA