Sharding-JDBC从入门到精通(3)- Sharding-JDBC 入门程序
一、Sharding-JDBC 入门程序(水平分表)-环境搭建
1、需求说明
使用 Sharding-JDBC 完成对订单表的水平分表,通过快速入门程序的开发,快速体验 Sharding-JDBc 的使用方法。
人工创建两张表,t order_1 和 t_order 2, 这两张表是订单表拆分后的表,通过 Sharding-Jdbc 向订单表插入数据,按照一定的分片规则,主键为偶数的进入 t_order_1, 另一部分数据进入 t_order_2,通过 Sharding-Jdbc 查询数据,根据 SQL 语句的内容从 t_order 1 或 t_order_2 查询数据。
2、环境说明
- 操作系统: Win10
- 数据库: MySQL-5.7.25
- JDK : 64位jdk1.8.0_201
- 应用框架: spring-boot-2.1.3.RELEASE, Mybatis3.5.0
- Sharding-jDBc:sharding-jdbc-spring-bootkstarter-4.0.0-Rc1
3、创建数据库
3.1 创建订单库 order_db
CREATE DATABASE `order_db` CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';
3.2 在 order_db 中创建 t_order_1 和 t_order_2 表
# 创建 t_order_1 表DROP TABLE IF EXISTS `t_order_1`;CREATE TABLE `t_order_1` (
`order_id` BIGINT(20) NOT NULL COMMENT '订单id',
`price` DECIMAL(10,2) NOT NULL COMMENT '订单价格',
`user_id` BIGINT(20) NOT NULL COMMENT '下单用户id',
`status` VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '订单状态',
PRIMARY KEY(`order_id`) USING BTREE
) ENGINE = INNODB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC;# 创建 t_order_2 表DROP TABLE IF EXISTS `t_order_2`;CREATE TABLE `t_order_2` (
`order_id` BIGINT(20) NOT NULL COMMENT '订单id',
`price` DECIMAL(10,2) NOT NULL COMMENT '订单价格',
`user_id` BIGINT(20) NOT NULL COMMENT '下单用户id',
`status` VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '订单状态',
PRIMARY KEY(`order_id`) USING BTREE
) ENGINE = INNODB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC;
4、打开 idea 创建 artifactId 名为 dbsharding 的 maven 父工程。
--> idea --> File --> New --> Project --> Maven Project SDK: ( 1.8(java version "1.8.0_131" ) --> Next --> Groupld : ( djh.it )Artifactld : ( dbsharding )Version : 1.0-SNAPSHOT--> Name: ( dbsharding )Location: ( ...\dbsharding\ ) --> Finish
5、在 dbsharding 父工程的 pom.xml 文件中导入依赖坐标。
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>djh.it</groupId><artifactId>dbsharding</artifactId><packaging>pom</packaging><version>1.0-SNAPSHOT</version><modules><module>sharding_jdbc_simple</module></modules><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.3.RELEASE</version></parent><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version></properties><dependencyManagement><dependencies><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.9.2</version></dependency><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId><version>2.9.2</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.0</version></dependency><dependency><groupId>javax.interceptor</groupId><artifactId>javax.interceptor-api</artifactId><version>1.2</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.46</version></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.0.0</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.1.16</version></dependency><dependency><groupId>org.apache.shardingsphere</groupId><artifactId>sharding-jdbc-spring-boot-starter</artifactId><version>4.0.0-RC1</version></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.1.0</version></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator</artifactId><version>3.1.0</version></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-typehandlers-jsr310</artifactId><version>1.0.2</version></dependency></dependencies></dependencyManagement></project>
<!-- ...\dbsharding\pom.xml -->
6、打开 idea 创建 artifactId 名为 sharding_jdbc_simple 的 maven 子工程(子模块)。
--> idea --> 右键 dbsharding 父工程 --> New --> Module...--> Maven Project SDK: ( 1.8(java version "1.8.0_131" ) --> Next --> Groupld : ( djh.it )Artifactld : ( sharding_jdbc_simple )Version : 1.0-SNAPSHOT--> Module Name: ( sharding_jdbc_simple )Content root: ( ...\dbsharding\sharding_jdbc_simple )Module file location: ( ...\dbsharding\sharding_jdbc_simple ) --> Finish
7、在 sharding_jdbc_simple 子工程(子模块)的 pom.xml 文件中导入依赖坐标。
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>dbsharding</artifactId><groupId>djh.it</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>sharding_jdbc_simple</artifactId><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>org.apache.shardingsphere</groupId><artifactId>sharding-jdbc-spring-boot-starter</artifactId></dependency></dependencies></project>
<!-- ...\dbsharding\sharding_jdbc_simple\pom.xml -->
8、在 sharding_jdbc_simple 子工程(子模块)中,创建启动类 ShardingJdbcSimpleBootstrap.java。
/*** D:\Java\java-test\idea\dbsharding\sharding_jdbc_simple\src\main\java\djh\it\dbsharding\simple\ShardingJdbcSimpleBootstrap.java** 2024-6-28 创建启动类 ShardingJdbcSimpleBootstrap.java*/
package djh.it.dbsharding.simple;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class ShardingJdbcSimpleBootstrap {public static void main(String[] args) {SpringApplication.run(ShardingJdbcSimpleBootstrap.class, args);}
}
二、Sharding-JDBC 入门程序(水平分表)-分片配置
1、分片规则配置
分片规则配置是 sharding-jdbc 进行对分库分表操作的重要依据,配置内容包括:数据源、主键生成策略、分片策略等。需要在工程的 application.properties 配置文件中配置。
- 1.首先定义数据源 m1,并对 m1 进行实际的参数配置。
- 2.指定 t_order 表的数据分布情况,他分布在 m1.t_order_1, m1.t_order_2
- 3.指定 t_order 表的主键生成策略为 SNOWFLAKE, SNOWFLAKE 是一种分布式自增算法,保证 id 全局唯一
- 4.定义 t_order 分片策略,order_id 为偶数的数据落在 t_order_1, 为奇数的落在 t_order_2, 分表策略的表达式为 t_order_$->{order_id % 2+ 1}
2、在 sharding_jdbc_simple 子工程(子模块)中,创建 application.properties 配置文件
# dbsharding\sharding_jdbc_simple\src\main\resources\application.propertiesserver.port = 56081spring.application.name = sharding-jdbc-simple-demoserver.servlet.context-path = /sharding-jdbc-simple-demo
spring.http.encoding.enabled = true
spring.http.encoding.charset = utf-8
spring.http.encoding.force = truespring.main.allow-bean-definition-overriding = true
mybatis.configuration.map-underscore-to-camel-case = true# 配置 sharding-jdbc 分片规则
# 定义数据源(定义数据源名为 m1)
spring.shardingsphere.datasource.names = m1spring.shardingsphere.datasource.m1.type = com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m1.driver-class-name = com.mysql.jdbc.Driver
spring.shardingsphere.datasource.m1.url = jdbc:mysql://localhost:3306/order_db?useUnicode=true
spring.shardingsphere.datasource.m1.username = root
spring.shardingsphere.datasource.m1.password = 12311# 指定 t_order 表的数据分布情况,配置数据节点(t_order 映射到 t_order_1 或者 t_order_2)
spring.shardingsphere.sharding.tables.t_order.actual-data-nodes = m1.t_order_$->{1..2}# 指定 t_order 表的主键生成策略为 SNOWFLAKE(雪花算法)
spring.shardingsphere.sharding.tables.t_order.key-generator.column = order_id
spring.shardingsphere.sharding.tables.t_order.key-generator.type = SNOWFLAKE# 指定 t_order 表的分片策略,分片策略包括分片键和分片算法
spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.sharding-column = order_id
spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.algorithm-expression = t_order_$->{order_id % 2 + 1}# 打开 sql 输出日志
spring.shardingsphere.props.sql.show = trueswagger.enable = truelogging.level.root = info
logging.level.org.springframework.web = info
logging.level.djh.it.dbsharding = debug
logging.level.druid.sql = debug
三、Sharding-JDBC 入门程序(水平分表)-插入订单
1、在 sharding_jdbc_simple 子工程(子模块)中,创建 dao 接口类 OrderDao.java
/*** D:\Java\java-test\idea\dbsharding\sharding_jdbc_simple\src\main\java\djh\it\dbsharding\simple\dao\OrderDao.java** 2024-5-28 创建 dao 接口类 OrderDao.java*/
package djh.it.dbsharding.simple.dao;import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Component;import java.math.BigDecimal;@Mapper
@Component
public interface OrderDao {@Insert("insert into t_order(price, user_id, status) values(#{price}, #{userId}, #{status})")int insertOrder(@Param("price") BigDecimal price, @Param("userId")Long userId, @Param("status")String status);
}
2、在 sharding_jdbc_simple 子工程(子模块)中,创建 接口 OrderDao 的测试类 testInsertOrder.java 进行测试
/*** dbsharding\sharding_jdbc_simple\src\test\java\djh\it\dbsharding\simple\dao\OrderDaoTest.java** 2024-6-28 创建 接口 OrderDao 的测试类 OrderDaoTest.java 进行测试** 快速生成 接口 OrderDao 类的测试类:* 1)右键 接口 OrderDao 选择 【Generate...】* 2)选择【Test..】* 3)Testing library : JUnit4* Class name : OrderDaoTest* SUPERCLASS : 空* Destination package : djh.it.dbsharding.simple.dao* 4)点击 OK。*/
package djh.it.dbsharding.simple.dao;import djh.it.dbsharding.simple.ShardingJdbcSimpleBootstrap;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;import java.math.BigDecimal;@RunWith(SpringRunner.class)
@SpringBootTest(classes = {ShardingJdbcSimpleBootstrap.class})
public class OrderDaoTest {@AutowiredOrderDao orderDao;@Testpublic void testInsertOrder(){//orderDao.insertOrder(new BigDecimal(11 ),1L, "SUCCESS");for(int i=1; i<20; i++){orderDao.insertOrder(new BigDecimal(i ),1L, "success2");}}
}
四、Sharding-JDBC 入门程序(水平分表)-查询订单
1、在 sharding_jdbc_simple 子工程(子模块)中,修改 dao 接口类 OrderDao.java 添加 查询订单的方法。
/*** D:\Java\java-test\idea\dbsharding\sharding_jdbc_simple\src\main\java\djh\it\dbsharding\simple\dao\OrderDao.java** 2024-5-28 创建 dao 接口类 OrderDao.java*/
package djh.it.dbsharding.simple.dao;import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Component;import java.math.BigDecimal;
import java.util.List;
import java.util.Map;@Mapper
@Component
public interface OrderDao {//查询数据:根据订单ID ( SQL 语句:SELECT * FROM t_order_1 WHERE order_id IN (1013467489922711552, 1013467489960460288); )@Select( "<script>" +"select" +" * " +" from t_order t " +" where t.order_id in " +" <foreach collection=' orderIds' open='(' separator=',' close=')' item='id'>" +" #{id} " +" </foreach>" +"</script>" )List<Map> selectOrderByIds(@Param("orderIds") List<Long> orderIds);//插入数据@Insert("insert into t_order(price, user_id, status) values(#{price}, #{userId}, #{status})")int insertOrder(@Param("price") BigDecimal price, @Param("userId")Long userId, @Param("status")String status);
}
2、在 sharding_jdbc_simple 子工程(子模块)中,修改 接口 OrderDao 的测试类 testInsertOrder.java 添加 查询订单的方法。进行测试
/*** dbsharding\sharding_jdbc_simple\src\test\java\djh\it\dbsharding\simple\dao\OrderDaoTest.java** 2024-6-28 创建 接口 OrderDao 的测试类 OrderDaoTest.java 进行测试** 快速生成 接口 OrderDao 类的测试类:* 1)右键 接口 OrderDao 选择 【Generate...】* 2)选择【Test..】* 3)Testing library : JUnit4* Class name : OrderDaoTest* SUPERCLASS : 空* Destination package : djh.it.dbsharding.simple.dao* 4)点击 OK。*/
package djh.it.dbsharding.simple.dao;import djh.it.dbsharding.simple.ShardingJdbcSimpleBootstrap;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;@RunWith(SpringRunner.class)
@SpringBootTest(classes = {ShardingJdbcSimpleBootstrap.class})
public class OrderDaoTest {@AutowiredOrderDao orderDao;@Testpublic void testSelectOrderByIds(){List<Long> ids = new ArrayList<>();ids.add(1013467489922711552L); //此order_id 在 t_order_1 表中,ids.add(1013465458055053313L); //此order_id 在 t_order_2 表中,List<Map> maps = orderDao.selectOrderByIds(ids);System.out.println(maps);}@Testpublic void testInsertOrder(){//orderDao.insertOrder(new BigDecimal(11 ),1L, "SUCCESS");for(int i=1; i<20; i++){orderDao.insertOrder(new BigDecimal(i ),1L, "success2");}}
}
五、Sharding-JDBC 入门程序(水平分表)-执行流程分析
1、执行流程分析
通过日志分析,Sharding-JDBC 在拿到用户要执行的sql之后干了哪些事儿:
- (1) 解析 sql,获取片键值,在本例中是 order id。
- (2) sharding-JDBC 通过规则配置。 t_order_$->{order_id%2+1},知道了当 order_id 为偶数时,应该往 t_order_1 表插数据,为奇数时,往 t_order_2 插数据。
- (3) 于是 Sharding-JDBC 根据 order_id 的值改写 sql 语句,改写后的 SQL 语句是真实所要执行的SQL语句。
- (4) 执行改写后的真实 sql 语句
- (5) 将所有真正执行 sql 的结果进行汇总合并,返回。
2、总结:Sharding-JDBC 根据分片策略(分片键 + 分片算法),改写 SQL 语句,执行真实 SQL 语句。
上一节关联链接请点击
# Sharding-JDBC从入门到精通(2)- Sharding-JDBC 介绍