开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第1天,点击查看活动详情
ShardingSphere5.2.0发布有一段时间了,包含了很多新的特性,新版本在功能、性能、测试、文档、示例等方面都进行了大量的优化。接下来我们就用数篇文章来介绍ShardingSphere5.2.0的使用。
1.项目准备
我们采用如下几个环境进行准备,jdk的话我们进行了升级,采用JDK11进行开发
-
开发工具:IntelliJIdea
-
数据库:mysql 8.X
-
框架:Springboot
-
JDK版本: 11
2.数据库准备
新建两个数据库,db1、db2,并在这两个数据库分辨新建t_order_0、t_order_1这两个表,建表语句如下:
#第一个数据库
create database db1;
use db1;
create table db1.t_order_0
(
order_id bigint not null comment 'order_id'
primary key,
user_id bigint not null comment '用户id'
);
create table db1.t_order_1
(
order_id bigint not null comment 'order_id'
primary key,
user_id bigint not null comment '用户id'
);
#第二个数据库
create database db2;
use db2;
create table db2.t_order_0
(
order_id bigint not null comment 'order_id'
primary key,
user_id bigint not null comment '用户id'
);
create table db2.t_order_1
(
order_id bigint not null comment 'order_id'
primary key,
user_id bigint not null comment '用户id'
);
3.用Idea快速搭建一个项目
本本文章是基于ShardingSphere最新的版本5.2.0搭建,首先我们点击idea的File->New->Project新建一个项目。
然后点击Next
引入项目相关依
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.daiyu</groupId>
<artifactId>ShardingSphere-Learn</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>ShardingSphere-Learn</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.5.6</spring-boot.version>
<mybatis-plus.version>3.5.2</mybatis-plus.version>
<knife4j.version>3.0.3</knife4j.version>
<sharding.version>5.2.0</sharding.version>
<druid.version>1.2.9</druid.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>${knife4j.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<!--sharding相关依赖-->
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
<version>${sharding.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.3.7.RELEASE</version>
<configuration>
<mainClass>com.daiyu.sharding.ShardingSphereLearnApplication</mainClass>
</configuration>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
3.接下来简单的配置下Sharidng的分库分表的策略
在项目的application.yml配置分库分表的策略,详细配置如下:
server.port=8080
spring.application.name=ShardingSphere-Learn
#knife4j
knife4j.enable=true
#mybatis-plus
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
mybatis-plus.configuration.map-underscore-to-camel-case=true
mybatis-plus.mapper-locations=classpath:**/*.xml
mybatis-plus.type-aliases-package=com.daiyu.sharding.domain.entity
#sharidng的数据库连接配置
spring.shardingsphere.datasource.ds-1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.ds-1.password=123456
spring.shardingsphere.datasource.ds-1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds-1.url=jdbc:mysql://localhost:3308/db1?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=false
spring.shardingsphere.datasource.ds-1.username=root
spring.shardingsphere.datasource.ds-2.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.ds-2.password=123456
spring.shardingsphere.datasource.ds-2.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds-2.url=jdbc:mysql://localhost:3308/db2?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=false
spring.shardingsphere.datasource.ds-2.username=root
spring.shardingsphere.datasource.names=ds-1,ds-2
spring.shardingsphere.props.sql-show=true
spring.shardingsphere.rules.sharding.default-database-strategy.standard.sharding-algorithm-name=database-inline
spring.shardingsphere.rules.sharding.default-database-strategy.standard.sharding-column=user_id
#sharding的分片算法
spring.shardingsphere.rules.sharding.sharding-algorithms.database-inline.props.algorithm-expression=ds-$->{user_id % 2 +1}
spring.shardingsphere.rules.sharding.sharding-algorithms.database-inline.type=INLINE
spring.shardingsphere.rules.sharding.sharding-algorithms.table-inline.props.algorithm-expression=t_order_$->{order_id % 2}
spring.shardingsphere.rules.sharding.sharding-algorithms.table-inline.type=INLINE
spring.shardingsphere.rules.sharding.tables.t_order.actual-data-nodes=ds-$->{1..2}.t_order_$->{0..1}
spring.shardingsphere.rules.sharding.tables.t_order.table-strategy.standard.sharding-algorithm-name=table-inline
spring.shardingsphere.rules.sharding.tables.t_order.table-strategy.standard.sharding-column=order_id
spring.shardingsphere.rules.sharding.binding-tables=t_order
4.编写实体类
package com.daiyu.sharding.domain.entity;
import lombok.Data;
@Data
public class Order {
/**
* order_id
*/
private Long orderId;
/**
* 用户id
*/
private Long userId;
}
5.编写service
package com.daiyu.sharding.service.Impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.daiyu.sharding.domain.entity.Order;
import com.daiyu.sharding.domain.request.OrderReq;
import com.daiyu.sharding.domain.response.OrderRsp;
import com.daiyu.sharding.mapper.OrderMapper;
import com.daiyu.sharding.service.OrderService;
import kotlin.jvm.internal.Lambda;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.sql.Array;
import java.util.ArrayList;
import java.util.List;
/**
* @author :chenlong
* @filename OrderServiceImpl
* @date 2022-09-12 16:57
* @description:orderservice实现类
*/
@Slf4j
@Service
public class OrderServiceImpl implements OrderService {
@Resource
private OrderMapper orderMapper;
@Override
public List<OrderRsp> getOrderInfo() {
LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<Order>();
List<Order> list = orderMapper.selectList(queryWrapper);
List<OrderRsp> orderList = new ArrayList<>();
list.stream().forEach(order -> {
OrderRsp orderRsp = new OrderRsp();
BeanUtils.copyProperties(order, orderRsp);
orderList.add(orderRsp);
});
return orderList;
}
@Override
public int insertOrder(Order order) {
return orderMapper.insert(order);
}
}
6.编写controller
package com.daiyu.sharding.controller;
import com.daiyu.sharding.common.core.JsonResult;
import com.daiyu.sharding.domain.entity.Order;
import com.daiyu.sharding.domain.response.OrderRsp;
import com.daiyu.sharding.service.OrderService;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
/**
* @author :daiyu
* @filename OrderController
* @date 2022-09-12 16:59
* @description:
*/
@Slf4j
@Api(tags = "订单相关接口")
@RestController
@RequestMapping("/order")
public class OrderController {
@Resource
private OrderService orderService;
@ApiOperationSupport(author = "daiyu")
@ApiOperation(value = "查询订单", notes = "查询订单")
@GetMapping("/search")
public JsonResult<List<OrderRsp>> getOrderInfo() {
List<OrderRsp> orderInfo = orderService.getOrderInfo();
JsonResult<List<OrderRsp>> jsonResult = new JsonResult<>();
jsonResult.setData(orderInfo);
return jsonResult;
}
@ApiOperationSupport(author = "daiyu")
@ApiOperation(value = "添加订单", notes = "添加订单")
@PostMapping("/add")
public JsonResult<Integer> addOrderInfo(Order order) {
int result = orderService.insertOrder(order);
JsonResult<Integer> jsonResult = new JsonResult<>();
jsonResult.setData(result);
return jsonResult;
}
}
7.编写Knife4j配置类
package com.daiyu.sharding.config;
import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
import io.swagger.annotations.ApiOperation;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* @author :daiyu
* @filename Knife4jConfig
* @date 2022-04-23 16:49
* @description:doc配置
*/
@Configuration
@EnableSwagger2
@EnableKnife4j
@Import(BeanValidatorPluginsConfiguration.class)
public class Knife4jConfig {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.useDefaultResponseMessages(false)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.daiyu.sharding.controller"))
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
.paths(PathSelectors.any())
.paths(PathSelectors.regex("(?!/error.*).*"))
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.description("接口测试文档")
.contact(new Contact("beyourself", "https://www", "xxx@qq.com"))
.version("v1.0")
.title("API测试文档")
.build();
}
}
8.编写统一返回
package com.daiyu.sharding.common.core;
import com.daiyu.sharding.common.exception.BaseErrorCodeEnum;
import lombok.extern.slf4j.Slf4j;
import java.io.Serializable;
/**
* 统一的Spring mvc响应结果封装对象
*
* @author daiyu
* @version 1.0
*/
@Slf4j
public class JsonResult<T> implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 请求成功
*/
private static final boolean REQUEST_SUCCESS = true;
/**
* 请求失败
*/
private static final boolean REQUEST_FAIL = false;
/**
* 默认错误码
*/
private static final String DEFAULT_ERROR_CODE = "-1";
/**
* 请求是否成功
*/
private Boolean success;
/**
* 业务数据
*/
private T data;
/**
* 错误码
*/
private String errorCode;
/**
* 错误提示语
*/
private String errorMessage;
public JsonResult() {
}
public JsonResult(Boolean success, T data, String errorCode, String errorMessage) {
this.success = success;
this.data = data;
this.errorCode = errorCode;
this.errorMessage = errorMessage;
}
/**
* 成功,不用返回数据
*
* @return
*/
public static <T> JsonResult<T> buildSuccess() {
return new JsonResult<>(REQUEST_SUCCESS, null, null, null);
}
/**
* 成功,返回数据
*
* @param data
* @return
*/
public static <T> JsonResult<T> buildSuccess(T data) {
return new JsonResult<>(REQUEST_SUCCESS, data, null, null);
}
/**
* 失败,固定状态码
*
* @param errorMsg
* @return
*/
public static <T> JsonResult<T> buildError(String errorMsg) {
return new JsonResult<>(REQUEST_FAIL, null, DEFAULT_ERROR_CODE, errorMsg);
}
/**
* 失败,自定义错误码和信息
*
* @param errorCode 错误码
* @param errorMsg 错误提示
* @return
*/
public static <T> JsonResult<T> buildError(String errorCode, String errorMsg) {
return new JsonResult<>(REQUEST_FAIL, null, errorCode, errorMsg);
}
/**
* 失败,枚举类定义错误码和信息
*
* @param baseErrorCodeEnum
* @return
*/
public static <T> JsonResult<T> buildError(BaseErrorCodeEnum baseErrorCodeEnum) {
return new JsonResult<>(REQUEST_FAIL, null, baseErrorCodeEnum.getErrorCode(), baseErrorCodeEnum.getErrorMsg());
}
public Boolean getSuccess() {
return success;
}
public void setSuccess(Boolean success) {
this.success = success;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public String getErrorCode() {
return errorCode;
}
public void setErrorCode(String errorCode) {
this.errorCode = errorCode;
}
public String getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
}
项目结构大致如下
9.运行下看效果
项目启动后的,在浏览器输入http://localhost:8080/doc.html,大致界面如下
发送请求,分别发送如下请求
#第一个请求
{
"orderId": 1,
"userId": 1
}
#第二个请求
{
"orderId": 1,
"userId": 2
}
#第三个请求
{
"orderId": 2,
"userId": 1
}
#第四个请求
{
"orderId": 2,
"userId": 2
}
然后idea控制台打印的日志
说名sharding已经将sql路由到对应的表
到此,我们的第一个ShardingSphere的demo启动完毕。