Spring Boot demo系列(十三):ShardingSphere + MyBatisPlus 分库分表
source link: https://segmentfault.com/a/1190000040300781
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
本文主要讲述了如何使用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("[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生成器文档。
先随机插入三条数据,刷新三次如下页面:
localhost:8080/test/user/insert
可以看到执行了三次插入操作,插入的三个表分别是:
test0.user2
test0.user0
test0.user2
因为这里测试的时候年龄都恰好是偶数,都插入到了test0
表。
查看数据:
http://localhost:8080/user/select
日志输出如下:
表示这是对六个表查询的结果,并将最后的结果进行聚合返回。
8 参考源码
Java
版:
Kotlin
版:
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK