Springboot 2.6 + Mybatis Plus 3.5 集成 Sharding-jdbc 5.1 分库分表
随着业务数据的增加,单个的数据库已经无法支撑系统运行了,为了提升系统的流畅性,分库分表就是为了解决系统在大量数据情况下系统相应时间的问题。Sharding-jdbc 作为成熟的分库分表技术框架,在国内应用广泛。本文将介绍基于 Springboot 2.6 + Mybatis Plus 3.5 集成 Sharding-jdbc 5.1 实现分库分表功能。
文章目录
1 摘要
随着业务数据的增加,单个的数据库已经无法支撑系统运行了,为了提升系统的流畅性,分库分表就是为了解决系统在大量数据情况下系统相应时间的问题。Sharding-jdbc 作为成熟的分库分表技术框架,在国内应用广泛。本文将介绍基于 Springboot 2.6 + Mybatis Plus 3.5 集成 Sharding-jdbc 5.1 实现分库分表功能。
Sharding-jdbc 官方文档: Use ShardingSphere Data Source in Spring
Sharding-jdbc 分库分表基本原理: 根据 id 进行取余,余数为多少,就对应相同编号的数据库、数据库表。
准备工作
数据库: 2个+
数据库表: 3个+
这里以最简分库分表为例: 一个单表(设备信息表),三张分表(路由器配置表)
./doc/sql/sharding_jdbc.sql
/*==============================================================*/
/* DBMS name: MySQL 5.0 */
/* Created on: 2022/4/7 10:35:20 */
/*==============================================================*/
DROP TABLE IF EXISTS DEVICE_INFO;
DROP TABLE IF EXISTS ROUTER_CONFIG_0;
DROP TABLE IF EXISTS ROUTER_CONFIG_1;
DROP TABLE IF EXISTS ROUTER_CONFIG_2;
/*==============================================================*/
/* Table: DEVICE_INFO */
/*==============================================================*/
CREATE TABLE DEVICE_INFO
(
ID BIGINT UNSIGNED NOT NULL COMMENT 'id',
TYPE TINYINT COMMENT '设备类型,1-路由器,2-音响,3-摄像头',
BRAND VARCHAR(32) COMMENT '设备品牌',
MODEL VARCHAR(32) COMMENT '设备型号',
NAME VARCHAR(32) COMMENT '设备名称',
CREATE_TIME DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
UPDATE_TIME DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (ID)
)
ENGINE = INNODB DEFAULT
CHARSET = UTF8MB4;
ALTER TABLE DEVICE_INFO COMMENT '设备信息';
/*==============================================================*/
/* Table: ROUTER_CONFIG_0 */
/*==============================================================*/
CREATE TABLE ROUTER_CONFIG_0
(
ID BIGINT UNSIGNED NOT NULL COMMENT '主键',
DEVICE_ID BIGINT COMMENT '设备id',
WIFI_NAME VARCHAR(32) COMMENT 'wifi名称',
WIFI_PASSWORD VARCHAR(64) COMMENT 'wifi密码',
ENCRYPT_TYPE TINYINT DEFAULT 0 COMMENT '加密类型,0-不加密,1-WPA-PSK,2-WPA2-PSK,3-WPA/WPA2-PSK',
ADMIN_PASSWORD VARCHAR(64) COMMENT '管理员密码',
WIFI_SWITCH TINYINT DEFAULT 1 COMMENT 'wifi开关,0-关闭,1-开启',
HIDE_SWITCH TINYINT DEFAULT 0 COMMENT '是否隐藏 wifi,0-不隐藏,1-隐藏',
CREATE_TIME DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
UPDATE_TIME DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (ID)
)
ENGINE = INNODB DEFAULT
CHARSET = UTF8MB4;
ALTER TABLE ROUTER_CONFIG_0 COMMENT '路由器配置信息';
/*==============================================================*/
/* Table: ROUTER_CONFIG_1 */
/*==============================================================*/
CREATE TABLE ROUTER_CONFIG_1
(
ID BIGINT UNSIGNED NOT NULL COMMENT '主键',
DEVICE_ID BIGINT COMMENT '设备id',
WIFI_NAME VARCHAR(32) COMMENT 'wifi名称',
WIFI_PASSWORD VARCHAR(64) COMMENT 'wifi密码',
ENCRYPT_TYPE TINYINT DEFAULT 0 COMMENT '加密类型,0-不加密,1-WPA-PSK,2-WPA2-PSK,3-WPA/WPA2-PSK',
ADMIN_PASSWORD VARCHAR(64) COMMENT '管理员密码',
WIFI_SWITCH TINYINT DEFAULT 1 COMMENT 'wifi开关,0-关闭,1-开启',
HIDE_SWITCH TINYINT DEFAULT 0 COMMENT '是否隐藏 wifi,0-不隐藏,1-隐藏',
CREATE_TIME DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
UPDATE_TIME DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (ID)
)
ENGINE = INNODB DEFAULT
CHARSET = UTF8MB4;
ALTER TABLE ROUTER_CONFIG_1 COMMENT '路由器配置信息';
/*==============================================================*/
/* Table: ROUTER_CONFIG_2 */
/*==============================================================*/
CREATE TABLE ROUTER_CONFIG_2
(
ID BIGINT UNSIGNED NOT NULL COMMENT '主键',
DEVICE_ID BIGINT COMMENT '设备id',
WIFI_NAME VARCHAR(32) COMMENT 'wifi名称',
WIFI_PASSWORD VARCHAR(64) COMMENT 'wifi密码',
ENCRYPT_TYPE TINYINT DEFAULT 0 COMMENT '加密类型,0-不加密,1-WPA-PSK,2-WPA2-PSK,3-WPA/WPA2-PSK',
ADMIN_PASSWORD VARCHAR(64) COMMENT '管理员密码',
WIFI_SWITCH TINYINT DEFAULT 1 COMMENT 'wifi开关,0-关闭,1-开启',
HIDE_SWITCH TINYINT DEFAULT 0 COMMENT '是否隐藏 wifi,0-不隐藏,1-隐藏',
CREATE_TIME DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
UPDATE_TIME DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (ID)
)
ENGINE = INNODB DEFAULT
CHARSET = UTF8MB4;
ALTER TABLE ROUTER_CONFIG_2 COMMENT '路由器配置信息';
注意事项:
无论是分库还是分表,编号都要从 0 开始。数据源名称 ds0,ds1,表名 table_0,table_1 因为取余匹配数据库、表会出现余数为 0 的情况
2 Maven 核心依赖
./demo-sharding-jdbc/pom.xml
<dependencies>
<!-- web mvc -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${springboot.version}</version>
</dependency>
<!-- sharding-jdbc -->
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
<version>${shardingsphere.version}</version>
</dependency>
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!-- mybatis plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<!-- hutool -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
其中对应的版本如下:
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<java.version>1.8</java.version>
<springboot.version>2.6.6</springboot.version>
<shardingsphere.version>5.1.0</shardingsphere.version>
<mysql.version>8.0.28</mysql.version>
<mybatis-plus.version>3.5.1</mybatis-plus.version>
<hutool.version>5.7.21</hutool.version>
</properties>
3 核心配置
3.1 公共配置
./demo-sharding-jdbc/src/main/resources/application.yml
## server
server:
port: 8950
## spring
spring:
application:
name: demo-sharding-jdbc
profiles:
active: dev
## mybatis-plus
mybatis-plus:
mapper-locations: classpath*:mybatis/*.xml
type-aliases-package: com.ljq.demo.springboot.sharding.jdbc.model.entity
./demo-sharding-jdbc/src/main/java/com/ljq/demo/springboot/sharding/jdbc/common/MybatisPlusConfig.java
package com.ljq.demo.springboot.sharding.jdbc.common;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @Description: MybatisPlus 配置信息
* @Author: junqiang.lu
* @Date: 2020/9/1
*/
@Configuration
public class MybatisPlusConfig {
/**
* 新的分页插件,一缓和二缓遵循 mybatis 的规则
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
3.2 只分表,不分库
./demo-sharding-jdbc/src/main/resources/application-dev.yml
## 不分库,分表
spring:
shardingsphere:
mode:
type: Memory ## Sharding-jdbc 运行模式
datasource:
names: ds1 ## 数据源别名
ds1:
type: com.zaxxer.hikari.HikariDataSource ## 数据源连接池连接类型,支持 Durid,Hikari 等常见数据库连接池
driver-class-name: com.mysql.cj.jdbc.Driver ## 数据库连接驱动
jdbc-url: "jdbc:mysql://127.0.0.1:3306/demo?useUnicode=true&characterEncoding=utf8\
&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2b8\
&useSSL=true&allowMultiQueries=true&autoReconnect=true&nullCatalogMeansCurrent=true"
username: root
password: "xxxx"
rules: ## 分库分表规则配置
sharding:
tables:
router_config: ## 数据库表名前缀
actual-data-nodes: ds1.router_config_$->{0..2} ## 实际表名
table-strategy: ## 分表策略
standard:
sharding-column: id ## 按照分表的列
sharding-algorithm-name: router-config-inline ## 分表算法名称(使用 yml 配置不能包含下划线,否则不生效)
key-generate-strategy: ## 主键生成策略
column: id ## 主键列
key-generator-name: snowflake ## 策略算法名称(推荐使用雪花算法)
sharding-algorithms:
router-config-inline:
type: INLINE
props:
algorithm-expression: router_config_$->{id % 3} ## 分表算法(取余)
key-generators:
snowflake:
type: SNOWFLAKE
props:
sql-show: true ## 展示执行 SQL
官方配置说明:
3.3 分库,不分表
./demo-sharding-jdbc/src/main/resources/application-test.yml
## 分库,不分表
spring:
shardingsphere:
datasource:
names: ds0,ds1
ds0:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: "jdbc:mysql://127.0.0.1:3306/demo?useUnicode=true&characterEncoding=utf8\
&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2b8\
&useSSL=true&allowMultiQueries=true&autoReconnect=true&nullCatalogMeansCurrent=true"
username: root
password: "xxxx"
ds1:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: "jdbc:mysql://127.0.0.1:3306/demo2?useUnicode=true&characterEncoding=utf8\
&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2b8\
&useSSL=true&allowMultiQueries=true&autoReconnect=true&nullCatalogMeansCurrent=true"
username: root
password: "xxxx"
rules:
sharding:
default-database-strategy:
standard:
sharding-column: id
sharding-algorithm-name: database-inline
tables:
device_info: ## 数据库表名
actual-data-nodes: ds$->{0..1}.device_info ## 实际表节点
key-generate-strategy:
column: id
key-generator-name: snowflake
sharding-algorithms:
database-inline:
type: INLINE
props:
algorithm-expression: ds$->{id % 2}
key-generators:
snowflake:
type: SNOWFLAKE
props:
sql-show: true
3.4 分库分表
./demo-sharding-jdbc/src/main/resources/application-prd.yml
## 分库,分表
spring:
shardingsphere:
mode:
type: Standalone
repository:
type: File
overwrite: true
datasource:
names: ds0,ds1
ds0:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: "jdbc:mysql://127.0.0.1:3306/demo?useUnicode=true&characterEncoding=utf8\
&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2b8\
&useSSL=true&allowMultiQueries=true&autoReconnect=true&nullCatalogMeansCurrent=true"
username: root
password: "xxxx"
ds1:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: "jdbc:mysql://127.0.0.1:3306/demo2?useUnicode=true&characterEncoding=utf8\
&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2b8\
&useSSL=true&allowMultiQueries=true&autoReconnect=true&nullCatalogMeansCurrent=true"
username: root
password: "xxxx"
rules:
sharding:
default-database-strategy:
standard:
sharding-column: id
sharding-algorithm-name: database-inline
tables:
router_config:
actual-data-nodes: ds$->{0..1}.router_config_$->{0..2}
table-strategy:
standard:
sharding-column: id
sharding-algorithm-name: t-router-config-inline
key-generate-strategy:
column: id
key-generator-name: snowflake
sharding-algorithms:
database-inline:
type: INLINE
props:
algorithm-expression: ds$->{id % 2}
t-router-config-inline:
type: INLINE
props:
algorithm-expression: router_config_$->{id % 3}
key-generators:
snowflake:
type: SNOWFLAKE
props:
sql-show: true
4 核心代码
4.1 实体类
基础实体类
./demo-sharding-jdbc/src/main/java/com/ljq/demo/springboot/sharding/jdbc/model/entity/BaseEntity.java
package com.ljq.demo.springboot.sharding.jdbc.model.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* @Description: 基础实体类
* @Author: junqiang.lu
* @Date: 2022/4/1
*/
@Data
public class BaseEntity implements Serializable {
private static final long serialVersionUID = 2494094207811184245L;
/**
* id
**/
@JsonSerialize(using= ToStringSerializer.class)
private Long id;
/**
* 创建时间
**/
@TableField(value = "CREATE_TIME")
private Date createTime;
/**
* 更新时间
**/
@TableField(value = "UPDATE_TIME")
private Date updateTime;
}
分表对应的实体类
./demo-sharding-jdbc/src/main/java/com/ljq/demo/springboot/sharding/jdbc/model/entity/RouterConfigEntity.java
package com.ljq.demo.springboot.sharding.jdbc.model.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.ToString;
/**
* @Description: 路由器配置实体
* @Author: junqiang.lu
* @Date: 2022/4/1
*/
@Data
@ToString(callSuper = true)
@TableName(value = "router_config")
public class RouterConfigEntity extends BaseEntity {
private static final long serialVersionUID = 4849091384661358788L;
/**
* 设备 ID
*/
private Long deviceId;
/**
* wifi 名称
*/
private String wifiName;
/**
* wifi 密码
*/
private String wifiPassword;
/**
* 加密类型,0-不加密,1-WPA-PSK,2-WPA2-PSK,3-WPA/WPA2-PSK
*/
private Integer encryptType;
/**
* 管理员密码
*/
private String adminPassword;
/**
* wifi开关,0-关闭,1-开启
*/
private Integer wifiSwitch;
/**
* 是否隐藏 wifi,0-不隐藏,1-隐藏
*/
private Integer hideSwitch;
}
注意事项:
对于分表的表名,使用逻辑表名,即实际表名包含编号,使用 Mybatis Plus 的 @TableName
不包含编号
只分库的数据库表对应的实体类
./demo-sharding-jdbc/src/main/java/com/ljq/demo/springboot/sharding/jdbc/model/entity/DeviceInfoEntity.java
package com.ljq.demo.springboot.sharding.jdbc.model.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.ToString;
/**
* @Description: 设备信息实体
* @Author: junqiang.lu
* @Date: 2022/4/1
*/
@Data
@ToString(callSuper = true)
@TableName(value = "device_info")
public class DeviceInfoEntity extends BaseEntity {
private static final long serialVersionUID = -8417097323674970608L;
/**
* 设备类型,1-路由器,2-音响,3-摄像头
*/
private Integer type;
/**
* 设备品牌
*/
private String brand;
/**
* 设备型号
*/
private String model;
/**
* 设备名称
*/
private String name;
}
对于只分库的表名,和源库中的表名保持一致就可以
4.2 DAO 层
DAO 层按照正常 Mybatis Plus 写法
./demo-sharding-jdbc/src/main/java/com/ljq/demo/springboot/sharding/jdbc/dao/RouterConfigDao.java
package com.ljq.demo.springboot.sharding.jdbc.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ljq.demo.springboot.sharding.jdbc.model.entity.RouterConfigEntity;
import org.springframework.stereotype.Repository;
/**
* @Description: 路由器配置 DAO
* @Author: junqiang.lu
* @Date: 2022/4/1
*/
@Repository
public interface RouterConfigDao extends BaseMapper<RouterConfigEntity> {
}
./demo-sharding-jdbc/src/main/java/com/ljq/demo/springboot/sharding/jdbc/dao/DeviceInfoDao.java
package com.ljq.demo.springboot.sharding.jdbc.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ljq.demo.springboot.sharding.jdbc.model.entity.DeviceInfoEntity;
import org.springframework.stereotype.Repository;
/**
* @Description: 设备信息 DAO
* @Author: junqiang.lu
* @Date: 2022/4/1
*/
@Repository
public interface DeviceInfoDao extends BaseMapper<DeviceInfoEntity> {
}
4.3 Service 层
Service 接口
./demo-sharding-jdbc/src/main/java/com/ljq/demo/springboot/sharding/jdbc/service/RouterConfigService.java
package com.ljq.demo.springboot.sharding.jdbc.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.ljq.demo.springboot.sharding.jdbc.model.entity.RouterConfigEntity;
import com.ljq.demo.springboot.sharding.jdbc.model.param.RouterConfigAddParam;
import com.ljq.demo.springboot.sharding.jdbc.model.param.RouterConfigQueryOneParam;
import com.ljq.demo.springboot.sharding.jdbc.model.param.RouterConfigQueryPageParam;
/**
* @Description: 路由器配置业务接口
* @Author: junqiang.lu
* @Date: 2022/4/1
*/
public interface RouterConfigService {
/**
* 路由器配置新增
*
* @param addParam
* @return
*/
RouterConfigEntity add(RouterConfigAddParam addParam);
/**
* 路由器配置查询单条
*
* @param queryOneParam
* @return
*/
RouterConfigEntity queryOne(RouterConfigQueryOneParam queryOneParam);
/**
* 路由器配置分页查询
*
* @param queryPageParam
* @return
*/
IPage<RouterConfigEntity> queryPage(RouterConfigQueryPageParam queryPageParam);
}
./demo-sharding-jdbc/src/main/java/com/ljq/demo/springboot/sharding/jdbc/service/DeviceInfoService.java
package com.ljq.demo.springboot.sharding.jdbc.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.ljq.demo.springboot.sharding.jdbc.model.entity.DeviceInfoEntity;
import com.ljq.demo.springboot.sharding.jdbc.model.param.DeviceInfoAddParam;
import com.ljq.demo.springboot.sharding.jdbc.model.param.DeviceInfoQueryOneParam;
import com.ljq.demo.springboot.sharding.jdbc.model.param.DeviceInfoQueryPageParam;
/**
* @Description: 设备信息业务接口
* @Author: junqiang.lu
* @Date: 2022/4/1
*/
public interface DeviceInfoService {
/**
* 设备信息新增
*
* @param addParam
* @return
*/
DeviceInfoEntity add(DeviceInfoAddParam addParam);
/**
* 设备信息查询单条
*
* @param queryOneParam
* @return
*/
DeviceInfoEntity queryOne(DeviceInfoQueryOneParam queryOneParam);
/**
* 设备信息分页查询
*
* @param queryPageParam
* @return
*/
IPage<DeviceInfoEntity> queryPage(DeviceInfoQueryPageParam queryPageParam);
}
Service 实现类
Service 实现类和单数据源 Mybatis Plus 使用方式一致
./demo-sharding-jdbc/src/main/java/com/ljq/demo/springboot/sharding/jdbc/service/impl/RouterConfigServiceImpl.java
package com.ljq.demo.springboot.sharding.jdbc.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ljq.demo.springboot.sharding.jdbc.dao.RouterConfigDao;
import com.ljq.demo.springboot.sharding.jdbc.model.entity.RouterConfigEntity;
import com.ljq.demo.springboot.sharding.jdbc.model.param.RouterConfigAddParam;
import com.ljq.demo.springboot.sharding.jdbc.model.param.RouterConfigQueryOneParam;
import com.ljq.demo.springboot.sharding.jdbc.model.param.RouterConfigQueryPageParam;
import com.ljq.demo.springboot.sharding.jdbc.service.RouterConfigService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.Objects;
/**
* @Description: 路由器配置业务实现类
* @Author: junqiang.lu
* @Date: 2022/4/1
*/
@Service("routerConfigService")
public class RouterConfigServiceImpl extends ServiceImpl<RouterConfigDao, RouterConfigEntity>
implements RouterConfigService {
/**
* 设备信息新增
*
* @param addParam
* @return
*/
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = {Exception.class})
@Override
public RouterConfigEntity add(RouterConfigAddParam addParam) {
RouterConfigEntity routerConfigEntity = new RouterConfigEntity();
BeanUtil.copyProperties(addParam, routerConfigEntity, CopyOptions.create().ignoreError().ignoreNullValue());
this.save(routerConfigEntity);
return routerConfigEntity;
}
/**
* 设备信息查询单条
*
* @param queryOneParam
* @return
*/
@Override
public RouterConfigEntity queryOne(RouterConfigQueryOneParam queryOneParam) {
return this.getById(queryOneParam.getId());
}
/**
* 设备信息分页查询
*
* @param queryPageParam
* @return
*/
@Override
public IPage<RouterConfigEntity> queryPage(RouterConfigQueryPageParam queryPageParam) {
IPage<RouterConfigEntity> page = new Page<>(queryPageParam.getCurrentPage(), queryPageParam.getPageSize());
LambdaQueryWrapper<RouterConfigEntity> queryWrapper = Wrappers.lambdaQuery();
queryWrapper.eq(Objects.nonNull(queryPageParam.getDeviceId()), RouterConfigEntity::getDeviceId,
queryPageParam.getDeviceId());
queryWrapper.orderBy(true,true,RouterConfigEntity::getId);
return this.page(page, queryWrapper);
}
}
./demo-sharding-jdbc/src/main/java/com/ljq/demo/springboot/sharding/jdbc/service/impl/DeviceInfoServiceImpl.java
package com.ljq.demo.springboot.sharding.jdbc.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ljq.demo.springboot.sharding.jdbc.dao.DeviceInfoDao;
import com.ljq.demo.springboot.sharding.jdbc.model.entity.DeviceInfoEntity;
import com.ljq.demo.springboot.sharding.jdbc.model.param.DeviceInfoAddParam;
import com.ljq.demo.springboot.sharding.jdbc.model.param.DeviceInfoQueryOneParam;
import com.ljq.demo.springboot.sharding.jdbc.model.param.DeviceInfoQueryPageParam;
import com.ljq.demo.springboot.sharding.jdbc.service.DeviceInfoService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.util.Objects;
/**
* @Description: 设备信息业务实现类
* @Author: junqiang.lu
* @Date: 2022/4/2
*/
@Service("deviceInfoService")
public class DeviceInfoServiceImpl extends ServiceImpl<DeviceInfoDao, DeviceInfoEntity> implements DeviceInfoService {
/**
* 设备信息新增
*
* @param addParam
* @return
*/
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = {Exception.class})
@Override
public DeviceInfoEntity add(DeviceInfoAddParam addParam) {
DeviceInfoEntity deviceInfoEntity = new DeviceInfoEntity();
BeanUtil.copyProperties(addParam, deviceInfoEntity, CopyOptions.create().ignoreError().ignoreNullValue());
this.save(deviceInfoEntity);
return deviceInfoEntity;
}
/**
* 设备信息查询单条
*
* @param queryOneParam
* @return
*/
@Override
public DeviceInfoEntity queryOne(DeviceInfoQueryOneParam queryOneParam) {
return this.getById(queryOneParam.getId());
}
/**
* 设备信息分页查询
*
* @param queryPageParam
* @return
*/
@Override
public IPage<DeviceInfoEntity> queryPage(DeviceInfoQueryPageParam queryPageParam) {
Page<DeviceInfoEntity> page = new Page<>(queryPageParam.getCurrentPage(), queryPageParam.getPageSize());
LambdaQueryWrapper<DeviceInfoEntity> queryWrapper = Wrappers.lambdaQuery();
queryWrapper.eq(Objects.nonNull(queryPageParam.getType()), DeviceInfoEntity::getType, queryPageParam.getType());
queryWrapper.orderBy(true, true, DeviceInfoEntity::getType);
return this.page(page, queryWrapper);
}
}
4.4 控制层
./demo-sharding-jdbc/src/main/java/com/ljq/demo/springboot/sharding/jdbc/controller/RouterConfigController.java
package com.ljq.demo.springboot.sharding.jdbc.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.ljq.demo.springboot.sharding.jdbc.model.entity.RouterConfigEntity;
import com.ljq.demo.springboot.sharding.jdbc.model.param.RouterConfigAddParam;
import com.ljq.demo.springboot.sharding.jdbc.model.param.RouterConfigQueryOneParam;
import com.ljq.demo.springboot.sharding.jdbc.model.param.RouterConfigQueryPageParam;
import com.ljq.demo.springboot.sharding.jdbc.service.RouterConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
/**
* @Description: 路由器配置控制层
* @Author: junqiang.lu
* @Date: 2022/4/1
*/
@RestController
@RequestMapping(value = "/api/sharding/jdbc/router/config")
public class RouterConfigController {
@Autowired
private RouterConfigService routerConfigService;
/**
* 路由器配置新增单条
*
* @param addParam
* @return
*/
@PostMapping(value = "/add", produces = {MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity<RouterConfigEntity> add(@RequestBody RouterConfigAddParam addParam) {
return ResponseEntity.ok(routerConfigService.add(addParam));
}
/**
* 路由器配置查询单条
*
* @param queryOneParam
* @return
*/
@GetMapping(value = "/query/one", produces = {MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity<RouterConfigEntity> queryOne(RouterConfigQueryOneParam queryOneParam) {
return ResponseEntity.ok(routerConfigService.queryOne(queryOneParam));
}
/**
* 路由器配置分页查询
*
* @param queryPageParam
* @return
*/
@GetMapping(value = "/query/page", produces = {MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity<IPage<RouterConfigEntity>> queryPage(RouterConfigQueryPageParam queryPageParam) {
return ResponseEntity.ok(routerConfigService.queryPage(queryPageParam));
}
}
./demo-sharding-jdbc/src/main/java/com/ljq/demo/springboot/sharding/jdbc/controller/DeviceInfoController.java
package com.ljq.demo.springboot.sharding.jdbc.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.ljq.demo.springboot.sharding.jdbc.model.entity.DeviceInfoEntity;
import com.ljq.demo.springboot.sharding.jdbc.model.param.DeviceInfoAddParam;
import com.ljq.demo.springboot.sharding.jdbc.model.param.DeviceInfoQueryOneParam;
import com.ljq.demo.springboot.sharding.jdbc.model.param.DeviceInfoQueryPageParam;
import com.ljq.demo.springboot.sharding.jdbc.service.DeviceInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
/**
* @Description: 设备信息控制层
* @Author: junqiang.lu
* @Date: 2022/4/2
*/
@RestController
@RequestMapping(value = "/api/sharding/jdbc/device")
public class DeviceInfoController {
@Autowired
private DeviceInfoService deviceInfoService;
/**
* 设备信息新增单条
*
* @param addParam
* @return
*/
@PostMapping(value = "/add", produces = {MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity<DeviceInfoEntity> add(@RequestBody DeviceInfoAddParam addParam) {
return ResponseEntity.ok(deviceInfoService.add(addParam));
}
/**
* 设备信息查询单条
*
* @param queryOneParam
* @return
*/
@GetMapping(value = "/query/one", produces = {MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity<DeviceInfoEntity> queryOne(DeviceInfoQueryOneParam queryOneParam) {
return ResponseEntity.ok(deviceInfoService.queryOne(queryOneParam));
}
/**
* 设备信息分页查询
*
* @param queryPageParam
* @return
*/
@GetMapping(value = "/query/page", produces = {MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity<IPage<DeviceInfoEntity>> queryPage(DeviceInfoQueryPageParam queryPageParam) {
return ResponseEntity.ok(deviceInfoService.queryPage(queryPageParam));
}
}
4.5 SpringBoot 启动类
./demo-sharding-jdbc/src/main/java/com/ljq/demo/springboot/sharding/jdbc/DemoShardingJdbcApplication.java
package com.ljq.demo.springboot.sharding.jdbc;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author lujunqiang
*/
@MapperScan(basePackages = {"com.ljq.demo.springboot.sharding.jdbc.dao"})
@SpringBootApplication
public class DemoShardingJdbcApplication {
public static void main(String[] args) {
SpringApplication.run(DemoShardingJdbcApplication.class, args);
}
}
5 测试
5.1 只分表,不分库
5.1.1 插入数据
分表请求接口:
http://127.0.0.1:8950/api/sharding/jdbc/router/config/add
请求方式: POST
请求参数:
{
"deviceId": "1",
"wifiName": "Lexus",
"wifiPassword": "OGBFs9Ksa2E0m8M",
"encryptType": 1,
"adminPassword": "vbo7u3kgPeFJYU6",
"wifiSwitch": 1,
"hideSwitch": 1
}
后台日志:
2022-04-12 19:18:36.781 INFO 21080 --- [nio-8950-exec-2] ShardingSphere-SQL : Logic SQL: INSERT INTO router_config ( id,
device_id,
wifi_name,
wifi_password,
encrypt_type,
admin_password,
wifi_switch,
hide_switch ) VALUES ( ?,
?,
?,
?,
?,
?,
?,
? )
2022-04-12 19:18:36.781 INFO 21080 --- [nio-8950-exec-2] ShardingSphere-SQL : SQLStatement: MySQLInsertStatement(setAssignment=Optional.empty, onDuplicateKeyColumns=Optional.empty)
2022-04-12 19:18:36.781 INFO 21080 --- [nio-8950-exec-2] ShardingSphere-SQL : Actual SQL: ds1 ::: INSERT INTO router_config_2 ( id,
device_id,
wifi_name,
wifi_password,
encrypt_type,
admin_password,
wifi_switch,
hide_switch ) VALUES (?, ?, ?, ?, ?, ?, ?, ?) ::: [1513838994770907137, 1, Lexus, OGBFs9Ksa2E0m8M, 1, vbo7u3kgPeFJYU6, 1, 1]
从日志可以看出,SQL 分为逻辑 SQL 以及实际执行的 SQL ,根据 id 取余,最终插入的表为 router_config_2
对比没有分表的数据插入
请求接口:
http://127.0.0.1:8950/api/sharding/jdbc/device/add
请求方式: POST
请求参数:
{
"type": 1,
"brand": "TP-LINK",
"model": "TL-WDR5620",
"name": "TP-LINK双频千兆路由169"
}
后台日志:
2022-04-12 19:22:13.147 INFO 21080 --- [nio-8950-exec-3] ShardingSphere-SQL : Logic SQL: INSERT INTO device_info ( id,
type,
brand,
model,
name ) VALUES ( ?,
?,
?,
?,
? )
2022-04-12 19:22:13.147 INFO 21080 --- [nio-8950-exec-3] ShardingSphere-SQL : SQLStatement: MySQLInsertStatement(setAssignment=Optional.empty, onDuplicateKeyColumns=Optional.empty)
2022-04-12 19:22:13.147 INFO 21080 --- [nio-8950-exec-3] ShardingSphere-SQL : Actual SQL: ds1 ::: INSERT INTO device_info ( id,
type,
brand,
model,
name ) VALUES (?, ?, ?, ?, ?) ::: [1513839902246326273, 1, TP-LINK, TL-WDR5620, TP-LINK双频千兆路由169]
从日志可以看出,实际执行SQL与逻辑SQL一致,对于同一数据库中不分表的数据库表,SQL 执行不受影响
5.1.2 查询单条
分表请求接口:
http://127.0.0.1:8950/api/sharding/jdbc/router/config/query/one?id=1510093606222135297
请求方式: GET
后台日志:
2022-04-12 19:24:19.691 INFO 21080 --- [nio-8950-exec-6] ShardingSphere-SQL : Logic SQL: SELECT id,device_id,wifi_name,wifi_password,encrypt_type,admin_password,wifi_switch,hide_switch,CREATE_TIME,UPDATE_TIME FROM router_config WHERE id=?
2022-04-12 19:24:19.691 INFO 21080 --- [nio-8950-exec-6] ShardingSphere-SQL : SQLStatement: MySQLSelectStatement(table=Optional.empty, limit=Optional.empty, lock=Optional.empty, window=Optional.empty)
2022-04-12 19:24:19.691 INFO 21080 --- [nio-8950-exec-6] ShardingSphere-SQL : Actual SQL: ds1 ::: SELECT id,device_id,wifi_name,wifi_password,encrypt_type,admin_password,wifi_switch,hide_switch,CREATE_TIME,UPDATE_TIME FROM router_config_1 WHERE id=? ::: [1510093606222135297]
从日志可以看出,也是根据 id 值先确定表,再执行查询
5.1.3 分页查询
分表请求接口:
http://127.0.0.1:8950/api/sharding/jdbc/router/config/query/page?currentPage=1&pageSize=10&deviceId=1
请求方式: GET
后台日志:
2022-04-12 19:27:52.471 INFO 21080 --- [nio-8950-exec-8] ShardingSphere-SQL : Logic SQL: SELECT COUNT(*) AS total FROM router_config WHERE (device_id = ?)
2022-04-12 19:27:52.471 INFO 21080 --- [nio-8950-exec-8] ShardingSphere-SQL : SQLStatement: MySQLSelectStatement(table=Optional.empty, limit=Optional.empty, lock=Optional.empty, window=Optional.empty)
2022-04-12 19:27:52.471 INFO 21080 --- [nio-8950-exec-8] ShardingSphere-SQL : Actual SQL: ds1 ::: SELECT COUNT(*) AS total FROM router_config_0 WHERE (device_id = ?) UNION ALL SELECT COUNT(*) AS total FROM router_config_1 WHERE (device_id = ?) UNION ALL SELECT COUNT(*) AS total FROM router_config_2 WHERE (device_id = ?) ::: [1, 1, 1]
2022-04-12 19:27:52.653 INFO 21080 --- [nio-8950-exec-8] ShardingSphere-SQL : Logic SQL: SELECT id,device_id,wifi_name,wifi_password,encrypt_type,admin_password,wifi_switch,hide_switch,CREATE_TIME,UPDATE_TIME FROM router_config
WHERE (device_id = ?) ORDER BY id ASC LIMIT ?
2022-04-12 19:27:52.653 INFO 21080 --- [nio-8950-exec-8] ShardingSphere-SQL : SQLStatement: MySQLSelectStatement(table=Optional.empty, limit=Optional[org.apache.shardingsphere.sql.parser.sql.common.segment.dml.pagination.limit.LimitSegment@5ac88e33], lock=Optional.empty, window=Optional.empty)
2022-04-12 19:27:52.653 INFO 21080 --- [nio-8950-exec-8] ShardingSphere-SQL : Actual SQL: ds1 ::: SELECT id,device_id,wifi_name,wifi_password,encrypt_type,admin_password,wifi_switch,hide_switch,CREATE_TIME,UPDATE_TIME FROM router_config_0
WHERE (device_id = ?) ORDER BY id ASC LIMIT ? ::: [1, 10]
2022-04-12 19:27:52.653 INFO 21080 --- [nio-8950-exec-8] ShardingSphere-SQL : Actual SQL: ds1 ::: SELECT id,device_id,wifi_name,wifi_password,encrypt_type,admin_password,wifi_switch,hide_switch,CREATE_TIME,UPDATE_TIME FROM router_config_1
WHERE (device_id = ?) ORDER BY id ASC LIMIT ? ::: [1, 10]
2022-04-12 19:27:52.654 INFO 21080 --- [nio-8950-exec-8] ShardingSphere-SQL : Actual SQL: ds1 ::: SELECT id,device_id,wifi_name,wifi_password,encrypt_type,admin_password,wifi_switch,hide_switch,CREATE_TIME,UPDATE_TIME FROM router_config_2
WHERE (device_id = ?) ORDER BY id ASC LIMIT ? ::: [1, 10]
从日志可以看出,实际执行的SQL是根据分表的数量执行了多次,然后将每个分表的查询结果聚合
5.2 只分库,不分表
5.2.1 插入数据
请求接口:
http://127.0.0.1:8950/api/sharding/jdbc/device/add
请求方式: POST
请求参数:
{
"type": 1,
"brand": "TP-LINK",
"model": "TL-WDR5620",
"name": "TP-LINK双频千兆路由992"
}
后台日志:
2022-04-12 19:33:43.878 INFO 15896 --- [nio-8950-exec-4] ShardingSphere-SQL : Logic SQL: INSERT INTO device_info ( id,
type,
brand,
model,
name ) VALUES ( ?,
?,
?,
?,
? )
2022-04-12 19:33:43.879 INFO 15896 --- [nio-8950-exec-4] ShardingSphere-SQL : SQLStatement: MySQLInsertStatement(setAssignment=Optional.empty, onDuplicateKeyColumns=Optional.empty)
2022-04-12 19:33:43.879 INFO 15896 --- [nio-8950-exec-4] ShardingSphere-SQL : Actual SQL: ds1 ::: INSERT INTO device_info ( id,
type,
brand,
model,
name ) VALUES (?, ?, ?, ?, ?) ::: [1513842798769786881, 1, TP-LINK, TL-WDR5620, TP-LINK双频千兆路由992]
日志中可以看出数据实际插入的数据库是根据 id 进行取余,然后得到的余数即为数据库的编码
5.2.2 查询单条
请求接口:
http://127.0.0.1:8950/api/sharding/jdbc/device/query/one?id=1511636056593956866
请求方式: GET
后台日志:
2022-04-12 19:39:31.695 INFO 15896 --- [nio-8950-exec-3] ShardingSphere-SQL : Logic SQL: SELECT id,type,brand,model,name,CREATE_TIME,UPDATE_TIME FROM device_info WHERE id=?
2022-04-12 19:39:31.695 INFO 15896 --- [nio-8950-exec-3] ShardingSphere-SQL : SQLStatement: MySQLSelectStatement(table=Optional.empty, limit=Optional.empty, lock=Optional.empty, window=Optional.empty)
2022-04-12 19:39:31.695 INFO 15896 --- [nio-8950-exec-3] ShardingSphere-SQL : Actual SQL: ds0 ::: SELECT id,type,brand,model,name,CREATE_TIME,UPDATE_TIME FROM device_info WHERE id=? ::: [1511636056593956866]
5.2.3 分页查询
请求接口:
http://127.0.0.1:8950/api/sharding/jdbc/device/query/page?currentPage=1&pageSize=10&type=1
请求方式: GET
后台日志:
2022-04-12 20:10:29.920 INFO 15896 --- [nio-8950-exec-7] ShardingSphere-SQL : Logic SQL: SELECT COUNT(*) AS total FROM device_info WHERE (type = ?)
2022-04-12 20:10:29.920 INFO 15896 --- [nio-8950-exec-7] ShardingSphere-SQL : SQLStatement: MySQLSelectStatement(table=Optional.empty, limit=Optional.empty, lock=Optional.empty, window=Optional.empty)
2022-04-12 20:10:29.920 INFO 15896 --- [nio-8950-exec-7] ShardingSphere-SQL : Actual SQL: ds0 ::: SELECT COUNT(*) AS total FROM device_info WHERE (type = ?) ::: [1]
2022-04-12 20:10:29.920 INFO 15896 --- [nio-8950-exec-7] ShardingSphere-SQL : Actual SQL: ds1 ::: SELECT COUNT(*) AS total FROM device_info WHERE (type = ?) ::: [1]
2022-04-12 20:10:30.196 INFO 15896 --- [nio-8950-exec-7] ShardingSphere-SQL : Logic SQL: SELECT id,type,brand,model,name,CREATE_TIME,UPDATE_TIME FROM device_info
WHERE (type = ?) ORDER BY type ASC LIMIT ?
2022-04-12 20:10:30.196 INFO 15896 --- [nio-8950-exec-7] ShardingSphere-SQL : SQLStatement: MySQLSelectStatement(table=Optional.empty, limit=Optional[org.apache.shardingsphere.sql.parser.sql.common.segment.dml.pagination.limit.LimitSegment@61585c7f], lock=Optional.empty, window=Optional.empty)
2022-04-12 20:10:30.196 INFO 15896 --- [nio-8950-exec-7] ShardingSphere-SQL : Actual SQL: ds0 ::: SELECT id,type,brand,model,name,CREATE_TIME,UPDATE_TIME FROM device_info
WHERE (type = ?) ORDER BY type ASC LIMIT ? ::: [1, 10]
2022-04-12 20:10:30.196 INFO 15896 --- [nio-8950-exec-7] ShardingSphere-SQL : Actual SQL: ds1 ::: SELECT id,type,brand,model,name,CREATE_TIME,UPDATE_TIME FROM device_info
WHERE (type = ?) ORDER BY type ASC LIMIT ? ::: [1, 10]
从执行语句可以看出,是先将每个数据库查询数据总条数查询出来,然后再分页查询每个数据库的数据,最后进行汇总
5.3 分库分表
5.3.1 插入数据
请求接口:
http://127.0.0.1:8950/api/sharding/jdbc/router/config/add
请求方式: POST
请求参数:
{
"deviceId": "1",
"wifiName": "Zoie",
"wifiPassword": "oWCRA6nfduiWZNi",
"encryptType": 1,
"adminPassword": "__2Z4NG6xvhpEQY",
"wifiSwitch": 1,
"hideSwitch": 1
}
后台日志:
2022-04-12 20:13:47.488 INFO 20788 --- [nio-8950-exec-2] ShardingSphere-SQL : Logic SQL: INSERT INTO router_config ( id,
device_id,
wifi_name,
wifi_password,
encrypt_type,
admin_password,
wifi_switch,
hide_switch ) VALUES ( ?,
?,
?,
?,
?,
?,
?,
? )
2022-04-12 20:13:47.489 INFO 20788 --- [nio-8950-exec-2] ShardingSphere-SQL : SQLStatement: MySQLInsertStatement(setAssignment=Optional.empty, onDuplicateKeyColumns=Optional.empty)
2022-04-12 20:13:47.489 INFO 20788 --- [nio-8950-exec-2] ShardingSphere-SQL : Actual SQL: ds1 ::: INSERT INTO router_config_2 ( id,
device_id,
wifi_name,
wifi_password,
encrypt_type,
admin_password,
wifi_switch,
hide_switch ) VALUES (?, ?, ?, ?, ?, ?, ?, ?) ::: [1513852877632000001, 1, Zoie, oWCRA6nfduiWZNi, 1, __2Z4NG6xvhpEQY, 1, 1]
从执行SQL可以看出数据库、数据库表都是经过id取余计算后得到的
5.3.2 请求单条
请求接口:
http://127.0.0.1:8950/api/sharding/jdbc/router/config/query/one?id=1510093606222135297
请求方式: GET
请求日志:
2022-04-12 20:16:11.335 INFO 20788 --- [nio-8950-exec-3] ShardingSphere-SQL : Logic SQL: SELECT id,device_id,wifi_name,wifi_password,encrypt_type,admin_password,wifi_switch,hide_switch,CREATE_TIME,UPDATE_TIME FROM router_config WHERE id=?
2022-04-12 20:16:11.335 INFO 20788 --- [nio-8950-exec-3] ShardingSphere-SQL : SQLStatement: MySQLSelectStatement(table=Optional.empty, limit=Optional.empty, lock=Optional.empty, window=Optional.empty)
2022-04-12 20:16:11.335 INFO 20788 --- [nio-8950-exec-3] ShardingSphere-SQL : Actual SQL: ds1 ::: SELECT id,device_id,wifi_name,wifi_password,encrypt_type,admin_password,wifi_switch,hide_switch,CREATE_TIME,UPDATE_TIME FROM router_config_1 WHERE id=? ::: [1510093606222135297]
5.3.3 分页查询
请求接口:
http://127.0.0.1:8950/api/sharding/jdbc/router/config/query/page?currentPage=1&pageSize=10&deviceId=1
请求方式: GET
后台日志:
2022-04-12 20:18:03.387 INFO 20788 --- [nio-8950-exec-5] ShardingSphere-SQL : Logic SQL: SELECT COUNT(*) AS total FROM router_config WHERE (device_id = ?)
2022-04-12 20:18:03.387 INFO 20788 --- [nio-8950-exec-5] ShardingSphere-SQL : SQLStatement: MySQLSelectStatement(table=Optional.empty, limit=Optional.empty, lock=Optional.empty, window=Optional.empty)
2022-04-12 20:18:03.387 INFO 20788 --- [nio-8950-exec-5] ShardingSphere-SQL : Actual SQL: ds0 ::: SELECT COUNT(*) AS total FROM router_config_0 WHERE (device_id = ?) UNION ALL SELECT COUNT(*) AS total FROM router_config_1 WHERE (device_id = ?) UNION ALL SELECT COUNT(*) AS total FROM router_config_2 WHERE (device_id = ?) ::: [1, 1, 1]
2022-04-12 20:18:03.387 INFO 20788 --- [nio-8950-exec-5] ShardingSphere-SQL : Actual SQL: ds1 ::: SELECT COUNT(*) AS total FROM router_config_0 WHERE (device_id = ?) UNION ALL SELECT COUNT(*) AS total FROM router_config_1 WHERE (device_id = ?) UNION ALL SELECT COUNT(*) AS total FROM router_config_2 WHERE (device_id = ?) ::: [1, 1, 1]
2022-04-12 20:18:03.633 INFO 20788 --- [nio-8950-exec-5] ShardingSphere-SQL : Logic SQL: SELECT id,device_id,wifi_name,wifi_password,encrypt_type,admin_password,wifi_switch,hide_switch,CREATE_TIME,UPDATE_TIME FROM router_config
WHERE (device_id = ?) ORDER BY id ASC LIMIT ?
2022-04-12 20:18:03.633 INFO 20788 --- [nio-8950-exec-5] ShardingSphere-SQL : SQLStatement: MySQLSelectStatement(table=Optional.empty, limit=Optional[org.apache.shardingsphere.sql.parser.sql.common.segment.dml.pagination.limit.LimitSegment@2fc3d159], lock=Optional.empty, window=Optional.empty)
2022-04-12 20:18:03.633 INFO 20788 --- [nio-8950-exec-5] ShardingSphere-SQL : Actual SQL: ds0 ::: SELECT id,device_id,wifi_name,wifi_password,encrypt_type,admin_password,wifi_switch,hide_switch,CREATE_TIME,UPDATE_TIME FROM router_config_0
WHERE (device_id = ?) ORDER BY id ASC LIMIT ? ::: [1, 10]
2022-04-12 20:18:03.633 INFO 20788 --- [nio-8950-exec-5] ShardingSphere-SQL : Actual SQL: ds0 ::: SELECT id,device_id,wifi_name,wifi_password,encrypt_type,admin_password,wifi_switch,hide_switch,CREATE_TIME,UPDATE_TIME FROM router_config_1
WHERE (device_id = ?) ORDER BY id ASC LIMIT ? ::: [1, 10]
2022-04-12 20:18:03.633 INFO 20788 --- [nio-8950-exec-5] ShardingSphere-SQL : Actual SQL: ds0 ::: SELECT id,device_id,wifi_name,wifi_password,encrypt_type,admin_password,wifi_switch,hide_switch,CREATE_TIME,UPDATE_TIME FROM router_config_2
WHERE (device_id = ?) ORDER BY id ASC LIMIT ? ::: [1, 10]
2022-04-12 20:18:03.633 INFO 20788 --- [nio-8950-exec-5] ShardingSphere-SQL : Actual SQL: ds1 ::: SELECT id,device_id,wifi_name,wifi_password,encrypt_type,admin_password,wifi_switch,hide_switch,CREATE_TIME,UPDATE_TIME FROM router_config_0
WHERE (device_id = ?) ORDER BY id ASC LIMIT ? ::: [1, 10]
2022-04-12 20:18:03.633 INFO 20788 --- [nio-8950-exec-5] ShardingSphere-SQL : Actual SQL: ds1 ::: SELECT id,device_id,wifi_name,wifi_password,encrypt_type,admin_password,wifi_switch,hide_switch,CREATE_TIME,UPDATE_TIME FROM router_config_1
WHERE (device_id = ?) ORDER BY id ASC LIMIT ? ::: [1, 10]
2022-04-12 20:18:03.634 INFO 20788 --- [nio-8950-exec-5] ShardingSphere-SQL : Actual SQL: ds1 ::: SELECT id,device_id,wifi_name,wifi_password,encrypt_type,admin_password,wifi_switch,hide_switch,CREATE_TIME,UPDATE_TIME FROM router_config_2
WHERE (device_id = ?) ORDER BY id ASC LIMIT ? ::: [1, 10]
分库分表的分页查询相对复杂一些,会先将同一个数据库中的多个分表数据联合查询,得到单库总条数,然后再汇总所有分库数据得到总的数据条数;每一个分库中的每一个分表都执行一条分页查询SQL,得到分页结果,最后将所有的结果聚合返回
6 推荐参考资料
Use ShardingSphere Data Source in Spring
【Sharding-JDBC】(一) 整合mybatis-plus 水平分表
7 Github 源码
Gtihub 源码地址 : https://github.com/Flying9001/springBootDemo
个人公众号:404Code,分享半个互联网人的技术与思考,感兴趣的可以关注.
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)