赞
踩
笔者日常:看朋友发了一篇关于ShardingSphere的文章,我对ShardingSphere挺感兴趣的,于是就学了下。
目录
ShardingSphere功能强大,本文学习使用Sharding-JDBC数据分片功能下的分库分表功能。
注:由于本文知识需要,所以上图做了一个简单说明。
注:本文会涉及到的一些ShardingSphere基础概念,建议先去https://shardingsphere.apa.../sharding/了解一下。
将职工按照不同的年龄段进行分库,按照不同的性别进行分表。具体需求为:age在[0, 50)的,分到younger库;age在[50, 100)的,分到older库;age>=100的,分到other库。其中younger库和older库又按照性别进行分表,男的录入staff_man表,女的录入staff_woman表,other库不区分男女,不论男女都直接录入staff表。
注:本文以实现此需求进行分库分表示例。
上图中的相关表,建表语句为:
- CREATE TABLE `staff_man` (
- `id` varchar(40) NOT NULL,
- `age` int(3) DEFAULT NULL,
- `name` varchar(10) DEFAULT NULL,
- `gender` char(1) DEFAULT NULL,
- PRIMARY KEY (`id`)
- ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-
- CREATE TABLE `staff_woman` (
- `id` varchar(40) NOT NULL,
- `age` int(3) DEFAULT NULL,
- `name` varchar(10) DEFAULT NULL,
- `gender` char(1) DEFAULT NULL,
- PRIMARY KEY (`id`)
- ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-
- CREATE TABLE `staff` (
- `id` varchar(40) NOT NULL,
- `age` int(3) DEFAULT NULL,
- `name` varchar(10) DEFAULT NULL,
- `gender` char(1) DEFAULT NULL,
- PRIMARY KEY (`id`)
- ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
注:这里先按照需求进行建库建表。
注:建库建表可以使用程序动态创建,不过考虑到本节知识主要讲述ShardingSphere分库分表的实现,就不再引
入其它知识来干扰主题了,所以这里手动创建库表。
软硬件环境说明:Windows10、IntelliJ IDEA、SpringBoot 2.1.4.RELEASE、MySQL、MyBatis。
在pom.xml中引入ShardingSphere分库分表依赖
这里直接给出本人完整的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>
- <parent>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-parent</artifactId>
- <version>2.1.4.RELEASE</version>
- <relativePath/> <!-- lookup parent from repository -->
- </parent>
- <groupId>com.aspire</groupId>
- <artifactId>sharding-database-table</artifactId>
- <version>0.0.1-SNAPSHOT</version>
- <name>sharding-database-table</name>
- <description>分库分表示例</description>
-
- <properties>
- <java.version>1.8</java.version>
- </properties>
-
- <dependencies>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-test</artifactId>
- <scope>test</scope>
- </dependency>
-
- <!-- lombok -->
- <dependency>
- <groupId>org.projectlombok</groupId>
- <artifactId>lombok</artifactId>
- <optional>true</optional>
- </dependency>
-
- <!--mybatis-->
- <dependency>
- <groupId>org.mybatis.spring.boot</groupId>
- <artifactId>mybatis-spring-boot-starter</artifactId>
- <version>2.0.0</version>
- </dependency>
-
-
- <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
- <dependency>
- <groupId>mysql</groupId>
- <artifactId>mysql-connector-java</artifactId>
- <version>8.0.15</version>
- </dependency>
-
- <!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
- <dependency>
- <groupId>com.alibaba</groupId>
- <artifactId>druid</artifactId>
- <version>1.1.10</version>
- </dependency>
-
- <!-- https://mvnrepository.com/artifact/io.shardingjdbc/sharding-jdbc-core -->
- <dependency>
- <groupId>io.shardingjdbc</groupId>
- <artifactId>sharding-jdbc-core</artifactId>
- <version>2.0.3</version>
- </dependency>
-
- </dependencies>
- <build>
- <plugins>
- <plugin>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-maven-plugin</artifactId>
- </plugin>
- </plugins>
- </build>
-
- </project>
提示:Sharding分片配置有四种方式
Java配置
Yaml配置
SpringBoot配置
Spring命名空间配置
注:可详见https://shardingsphere.apache.or...onfiguration/。
注:本人这里采用Java配置,是因为Java配置相对于其余三种方式来说,更容易让人理解,但是代价是与代
码耦合度较高。如果比较熟了,推荐使用Yaml配置、SpringBoot配置。
本人Sharding分片配置的相关类说明:
ShardingConfig:核心sharding分片配置类。该类中的主要配置步骤是:
第一步: 获取众多数据源。
第二步: 获取总配置类。
第三步: 获取其余配置信息(如果需要的话)。
第四步:定制指定逻辑表的切片(分库分表)策略。
第五步:将定制了自己的切片策略的表的配置规则,加入总配置中。
第六步:创建并返回sharding总数据源,注入容器。
DatabaseShardingAlgorithm:本人用于数据源分片的算法实现,为ShardingConfig服务。
StaffTableComplexKeysShardingAlgorithm:本人用于逻辑表分片的算法实现,为ShardingConfig服务。
StaffTableTableShardingAlgorithm:本人用于逻辑表分片的算法实现,为ShardingConfig服务。
注:StaffTableComplexKeysShardingAlgorithm和StaffTableTableShardingAlgorithm都是用于对同一个逻辑表
分片的算法实现,在这次的示例项目汇总,其实一个就够了,不过本人这里将两个常用的都进行了实现,
分别实现的是复合分片算法、精准分片算法。
本人Sharding分片配置的相关类的具体代码:
ShardingConfig:
- import com.alibaba.druid.pool.DruidDataSource;
- import com.aspire.shardingdatabasetable.config.algorithm.DatabaseShardingAlgorithm;
- import com.aspire.shardingdatabasetable.config.algorithm.StaffTableComplexKeysShardingAlgorithm;
- import com.aspire.shardingdatabasetable.config.algorithm.StaffTableTableShardingAlgorithm;
- import io.shardingjdbc.core.api.ShardingDataSourceFactory;
- import io.shardingjdbc.core.api.config.ShardingRuleConfiguration;
- import io.shardingjdbc.core.api.config.TableRuleConfiguration;
- import io.shardingjdbc.core.api.config.strategy.ComplexShardingStrategyConfiguration;
- import io.shardingjdbc.core.api.config.strategy.StandardShardingStrategyConfiguration;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
-
- import javax.sql.DataSource;
- import java.sql.SQLException;
- import java.util.*;
- import java.util.concurrent.ConcurrentHashMap;
-
- /**
- * 分库分表配置
- *
- * @author JustryDeng
- * @date 2019/5/30 9:54
- */
- @Configuration
- public class ShardingConfig {
-
- /**
- * 切片配置
- *
- * @return 数据源
- * @date 2019/5/30 21:04
- */
- @Bean
- public DataSource shardingCustomer() throws SQLException {
-
- // 第一步: 获取众多数据源
- Map<String, DataSource> dataSourceMap = getDatasourceMap();
-
- // 第二步: 获取总配置类
- ShardingRuleConfiguration shardingRuleConfig = getShardingRuleConfiguration();
-
- // 第三步: 获取其余配置信息(如果需要的话)
- Properties properties = getProperties();
-
- // 第四步: 定制指定逻辑表的切片(分库分表)策略
- List<TableRuleConfiguration> allTableRuleConfiguration = getAllTableRuleConfiguration();
-
- // 第五步: 将定制了自己的切片策略的表的配置规则,加入总配置中
- shardingRuleConfig.getTableRuleConfigs().addAll(allTableRuleConfiguration);
-
- // 第六步: 创建并返回sharding总数据源,注入容器
- return ShardingDataSourceFactory.createDataSource(dataSourceMap, shardingRuleConfig,
- new ConcurrentHashMap<>(16), properties);
- }
-
- /**
- * 对指定逻辑表进行切片(分库分表)个性化配置
- * 注:本人这里只配置了
- *
- * @return 定制的 指定表的分库分表配置
- * @date 2019/6/4 12:01
- */
- private List<TableRuleConfiguration> getAllTableRuleConfiguration() {
- List<TableRuleConfiguration> list = new ArrayList<>(8);
- // 配置staff表切片规则
- TableRuleConfiguration staffTableRuleConfig = new TableRuleConfiguration();
- // 逻辑表名
- staffTableRuleConfig.setLogicTable("staff");
- /*
- * 真实库表名
- *
- * 注:库与表之间使用【.】分割;
- * 注:库表与库表之间使用【,】分割
- * 下述inline表达式的结果即为 otherDb.staff, youngerDb.staff_man, youngerDb.staff_woman, olderDb.staff_man, olderDb.staff_woman
- */
- staffTableRuleConfig.setActualDataNodes("otherDb.staff, ${['youngerDb', 'olderDb']}.staff_${['man', 'woman']}");
- // 设置这张表的 分库策略(本人这里采用:标准分片策略)
- staffTableRuleConfig.setDatabaseShardingStrategyConfig(
- new StandardShardingStrategyConfiguration("age", DatabaseShardingAlgorithm.class.getName()));
- // 设置这张表的 分表策略(本人这里采用:精确分片算法实现的标准分片策略)
- StandardShardingStrategyConfiguration standardShardingStrategyConfiguration = new StandardShardingStrategyConfiguration(
- "gender", StaffTableTableShardingAlgorithm.class.getName(), null);
- staffTableRuleConfig.setTableShardingStrategyConfig(standardShardingStrategyConfiguration);
- list.add(staffTableRuleConfig);
- return list;
- }
-
- /**
- * 获取其余配置信息
- *
- * @return 其余配置信息
- * @date 2019/6/4 11:24
- */
- private Properties getProperties() {
- Properties properties = new Properties();
- // 打印出分库路由后的sql
- properties.setProperty("sql.show", "true");
- return properties;
- }
- /**
- * 获取切片总配置类
- *
- * @return 总配置类
- * @date 2019/6/4 11:24
- */
- private ShardingRuleConfiguration getShardingRuleConfiguration() {
-
- // sharding总配置类
- ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();
-
- // 设置全局默认库
- shardingRuleConfig.setDefaultDataSourceName("otherDb");
-
- // 设置全局默认分库的策略(本人这里采用:精确分片算法实现的标准分片策略)
- // 如果某个表,没有指定分库策略的话,那么会默认使用这个策略;如果某个表制定了自己的策略,那么就会走自己的策略不走这个默认策略
- shardingRuleConfig.setDefaultDatabaseShardingStrategyConfig(
- new StandardShardingStrategyConfiguration("age", DatabaseShardingAlgorithm.class.getName()));
-
- // 设置全局默认分表的策略(本人这里采用:复合分片策略)
- // 如果某个表,没有指定分表策略的话,那么会默认使用这个策略;如果某个表制定了自己的策略,那么就会走自己的策略不走这个默认策略
- ComplexShardingStrategyConfiguration complexShardingStrategyConfiguration = new ComplexShardingStrategyConfiguration(
- "age, gender", StaffTableComplexKeysShardingAlgorithm.class.getName());
- shardingRuleConfig.setDefaultTableShardingStrategyConfig(complexShardingStrategyConfiguration);
- return shardingRuleConfig;
- }
-
- /**
- * 获取数据源Map
- *
- * @return 获取数据源Map
- * @date 2019/6/4 10:06
- */
- private Map<String, DataSource> getDatasourceMap() {
- // 真实数据源map
- Map<String, DataSource> dataSourceMap = new HashMap<>(4);
-
- // 配置第一个数据源,对应库other
- DruidDataSource dataSourceDefault = new DruidDataSource();
- dataSourceDefault.setDriverClassName("com.mysql.cj.jdbc.Driver");
- dataSourceDefault.setUrl("jdbc:mysql://localhost:3306/other?characterEncoding=utf8&serverTimezone=GMT%2B8");
- dataSourceDefault.setUsername("root");
- dataSourceDefault.setPassword("dengshuai");
- dataSourceMap.put("otherDb", dataSourceDefault);
-
- // 配置第二个数据源,对应库younger
- DruidDataSource dataSourceYounger = new DruidDataSource();
- dataSourceYounger.setDriverClassName("com.mysql.cj.jdbc.Driver");
- dataSourceYounger.setUrl("jdbc:mysql://localhost:3306/younger?characterEncoding=utf8&serverTimezone=GMT%2B8");
- dataSourceYounger.setUsername("root");
- dataSourceYounger.setPassword("dengshuai");
- dataSourceMap.put("youngerDb", dataSourceYounger);
-
- // 配置第三个数据源,对应库older
- DruidDataSource dataSourceOlder = new DruidDataSource();
- dataSourceOlder.setDriverClassName("com.mysql.cj.jdbc.Driver");
- dataSourceOlder.setUrl("jdbc:mysql://localhost:3306/older?characterEncoding=utf8&serverTimezone=GMT%2B8");
- dataSourceOlder.setUsername("root");
- dataSourceOlder.setPassword("dengshuai");
- dataSourceMap.put("olderDb", dataSourceOlder);
- return dataSourceMap;
- }
-
- }
DatabaseShardingAlgorithm:
- import io.shardingjdbc.core.api.algorithm.sharding.PreciseShardingValue;
- import io.shardingjdbc.core.api.algorithm.sharding.standard.PreciseShardingAlgorithm;
-
- import java.util.Collection;
-
- /**
- * 数据源分片策略
- *
- * 注:本人这里采用的是【精确分片算法PreciseShardingAlgorithm】,类似的算法还有
- * 【范围分片算法】
- * 【复合分片算法】
- * 【Hint分片算法】
- *
- * @author JustryDeng
- * @date 2019/5/31 10:11
- */
- public class DatabaseShardingAlgorithm implements PreciseShardingAlgorithm<Integer> {
-
- /**
- * Sharding.
- *
- * @param availableTargetNames
- * 数据源(库)名称集合 或 真实表名称集合。
- *
- * 提示:数据库源一旦定下来了,那么对应有哪些可用的真实表也就随之定下来了。
- *
- * 注:这里为: 数据源(库)名称集合。
- * 如,本人此次示例中,设置了的数据源有otherDb、youngerDb、olderDb,
- * 那么availableTargetNames输出就应为[otherDb, youngerDb, olderDb]
- *
- * 注:因为是先路由定位库,再路由定位真实表;所以一旦库定下来了,那么真实表的集合就定下来了。
- * 以本人的此项目的库与表进行说明:
- * otherDb库只有表staff.
- * youngerDb库有表staff_man。staff_woman.
- * olderDb库有表staff_man。staff_woman.
- * 在进行表分片之前会先进性数据库(数据源)分片,在数据源分片时,就路由定下来了走
- * otherDb的话,那么这里定位真实表时,候选的真实表集合里只有staff;如果
- * 在数据源分片时,路由定下来了走youngerDb的话,那么这里定位真实表时,候选的
- * 真实表集合里只有staff_man和staff_woman;
- *
- * @param shardingValue
- * 分片键的值。
- * 如:本人此次示例中,要路由到那个数据库源,是由age为数据源分片键的,age的列类型为int,
- * 所以这里的泛型是Integer。
- * 如果分片键的类型是bigint的话,这里的泛型就应该是Long.
- * 如果分片键的类型是varchar/char的话,这里的泛型就应该是String.
- *
- * @return 路由后的SQL要使用的数据源(库)的名字 或 路由后的SQL要使用的真实表的名字
- * 注:这里为: 路由后的SQL要使用的数据源(库)的名字。
- */
- @Override
- public String doSharding(Collection<String> availableTargetNames,
- PreciseShardingValue<Integer> shardingValue) {
- double value = shardingValue.getValue() * 1.0 / 50;
- // 年龄在[0, 50)之间的,入youngerDb库
- if (value < 1) {
- return "youngerDb";
- // 年龄在[50, 100)之间的,入olderDb库
- } else if (value < 2) {
- return "olderDb";
- // 年龄在>=100的,入otherDb库
- } else {
- return "otherDb";
- }
-
- /// 注:如果数据源的名称有规律的话(P.S.该名称是我们自己起的,当然可以起得很有规律),
- /// 也可以动态将 分片建的值 与 对应 数据源名称关联起来,如
- // for (String each : availableTargetNames) {
- //
- // if (each.endsWith(shardingValue.getValue() % 2 + "")) {
- // return each;
- // }
- // }
- // throw new UnsupportedOperationException();
- }
- }
StaffTableComplexKeysShardingAlgorithm:
- import io.shardingjdbc.core.api.algorithm.sharding.ListShardingValue;
- import io.shardingjdbc.core.api.algorithm.sharding.ShardingValue;
- import io.shardingjdbc.core.api.algorithm.sharding.complex.ComplexKeysShardingAlgorithm;
-
- import java.util.*;
-
- /**
- * 自定义符合分片策略
- *
- * 用于处理使用多键作为分片键进行分片的场景,包含多个分片键的逻辑较复杂,需要应用开发者自行
- * 处理其中的复杂度。需要配合ComplexShardingStrategy使用。
- *
- * @author JustryDeng
- * @date 2019/5/31 10:11
- */
- public class StaffTableComplexKeysShardingAlgorithm implements ComplexKeysShardingAlgorithm {
-
- /**
- * Sharding.
- *
- * @param availableTargetNames
- * 可用的数据源(库)名称集合 或 可用的真实表名称集合。
- *
- * 提示:数据库源一旦定下来了,那么对应有哪些可用的真实表也就随之定下来了。
- *
- * 注:这里为: 数据源(库)名称集合。
- * 如,本人此次示例中,设置了的数据源有otherDb、youngerDb、olderDb,
- * 那么availableTargetNames输出就应为[otherDb, youngerDb, olderDb]
- *
- * 注:因为是先路由定位库,再路由定位真实表;所以一旦库定下来了,那么真实表的集合就定下来了。
- * 以本人的此项目的库与表进行说明:
- * otherDb库只有表staff.
- * youngerDb库有表staff_man。staff_woman.
- * olderDb库有表staff_man。staff_woman.
- * 在进行表分片之前会先进性数据库(数据源)分片,在数据源分片时,就路由定下来了走
- * otherDb的话,那么这里定位真实表时,候选的真实表集合里只有staff;如果
- * 在数据源分片时,路由定下来了走youngerDb的话,那么这里定位真实表时,候选的
- * 真实表集合里只有staff_man和staff_woman;
- *
- * @param shardingValues
- * 分片键的值。
- * 如:本人此次示例中,要路由到那个数据库源,是由age为数据源分片键的,age的列类型为int,
- * 所以这里的泛型是Integer。
- * 如果分片键的类型是bigint的话,这里的泛型就应该是Long.
- * 如果分片键的类型是varchar/char的话,这里的泛型就应该是String.
- * 注: ComplexKeysShardingAlgorithm算法,ShardingValue接口的实现是ListShardingValue。
- * 本人这里,shardingValues的toString形如
- * shardingValues:[
- * ListShardingValue(logicTableName=staff, columnName=age, values=[21]),
- * ListShardingValue(logicTableName=staff, columnName=gender, values=[女])
- * ]
- *
- * @return 路由后的SQL要使用的数据源(库)名字的集合 或 路由后的SQL要使用的真实表名字的集合
- */
- @Override
- public Collection<String> doSharding(Collection<String> availableTargetNames,
- Collection<ShardingValue> shardingValues) {
- List<String> list = new ArrayList<>(4);
- ListShardingValue listShardingValue;
- for (ShardingValue item : shardingValues) {
- // 将item拆箱转换为listShardingValue
- listShardingValue = (ListShardingValue)item;
- System.out.println("逻辑表:" + listShardingValue.getLogicTableName());
- System.out.println("列名:" + listShardingValue.getColumnName());
- System.out.println("改列的值:" + listShardingValue.getValues());
- }
-
- return list;
- }
- }
StaffTableTableShardingAlgorithm:
- import io.shardingjdbc.core.api.algorithm.sharding.PreciseShardingValue;
- import io.shardingjdbc.core.api.algorithm.sharding.standard.PreciseShardingAlgorithm;
-
- import java.util.Collection;
-
- /**
- * 表分片策略
- *
- * 提示:PreciseShardingAlgorithm接口的泛型,视对应分片键的数据类型而定
- * 如:列是字符串,那么这里是 String
- * 列是int,那么这里是 Integer
- * 列是bigint,那么这里是 Long
- *
- * @author JustryDeng
- * @date 2019/5/31 10:11
- */
- public class StaffTableTableShardingAlgorithm implements PreciseShardingAlgorithm<String> {
-
- /**
- * Sharding.
- *
- * @param availableTargetNames
- * 数据源(库)名称集合 或 真实表名称集合。
- *
- * 提示:数据库源一旦定下来了,那么对应有哪些可用的真实表也就随之定下来了。
- *
- * 注:这里为: 数据源(库)名称集合。
- * 如,本人此次示例中,设置了的数据源有otherDb、youngerDb、olderDb,
- * 那么availableTargetNames输出就应为[otherDb, youngerDb, olderDb]
- *
- * 注:因为是先路由定位库,再路由定位真实表;所以一旦库定下来了,那么真实表的集合就定下来了。
- * 以本人的此项目的库与表进行说明:
- * otherDb库只有表staff.
- * youngerDb库有表staff_man。staff_woman.
- * olderDb库有表staff_man。staff_woman.
- * 在进行表分片之前会先进性数据库(数据源)分片,在数据源分片时,就路由定下来了走
- * otherDb的话,那么这里定位真实表时,候选的真实表集合里只有staff;如果
- * 在数据源分片时,路由定下来了走youngerDb的话,那么这里定位真实表时,候选的
- * 真实表集合里只有staff_man和staff_woman;
- *
- * @param shardingValue
- * 分片键的值。
- * 如:本人此次示例中,路由至哪张表,是由gender为真实表分片键的,
- * gender的列类型为char,所以这里的泛型是String。
- * 如果分片键的类型是int的话,这里的泛型就应该是Integer.
- * 如果分片键的类型是bigint的话,这里的泛型就应该是Long.
- * 如果分片键的类型是varchar/char的话,这里的泛型就应该是String.
- *
- * @return 路由后的SQL要使用的数据源(库)的名字 或 路由后的SQL要使用的真实表的名字
- * 注:这里为 路由后的SQL要使用的真实表的名字
- */
- @Override
- public String doSharding(Collection<String> availableTargetNames,
- PreciseShardingValue<String> shardingValue) {
- // 根据本人的真实数据节点信息, 如果 可用表里面包含staff,说明一定用的是otherDb数据源,
- // 而该数据库里面只有一张表staff, 这里直接返回即可
- if (availableTargetNames.contains("staff")) {
- return "staff";
- }
- // 如果是youngerDb数据源 或 olderDb数据源 的话,会走到下面的逻辑
- String tmpGender = shardingValue.getValue();
- if ("男".equals(tmpGender)) {
- return "staff_man";
- } else if ("女".equals(tmpGender)) {
- return "staff_woman";
- }
- throw new UnsupportedOperationException();
- }
- }
StaffPO模型:
- import lombok.AllArgsConstructor;
- import lombok.Builder;
- import lombok.Data;
- import lombok.NoArgsConstructor;
-
- /**
- * 职工模型, 对应staff表
- *
- * @author JustryDeng
- * @date 2019/6/3 23:26
- */
- @Data
- @Builder
- @NoArgsConstructor
- @AllArgsConstructor
- public class StaffPO {
-
- /** 分布式主键id */
- private String id;
-
- /** 年龄 */
- private Integer age;
-
- /** 姓名 */
- private String name;
-
- /** 性别 */
- private String gender;
- }
ShardingDatabaseTableApplication启动类:
- import org.springframework.boot.SpringApplication;
- import org.springframework.boot.autoconfigure.SpringBootApplication;
- import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
- import org.springframework.transaction.annotation.EnableTransactionManagement;
-
- /**
- * 启动类
- *
- * @author JustryDeng
- * @date 2019/5/29 11:03
- */
- @SpringBootApplication
- @EnableTransactionManagement
- public class ShardingDatabaseTableApplication {
-
- public static void main(String[] args) {
- SpringApplication.run(ShardingDatabaseTableApplication.class, args);
- }
-
- }
ShardingService业务接口:
- import com.aspire.shardingdatabasetable.model.StaffPO;
-
- import java.util.List;
-
- /**
- * Service层
- *
- * @author JustryDeng
- * @date 2019/5/29 17:35
- */
- public interface ShardingService {
-
- /**
- * 插入测试
- *
- * @param staffPO
- * 职工模型
- * @return 受影响行数
- * @date 2019/6/3 23:42
- */
- int insertDemo(StaffPO staffPO);
-
- /**
- * 查询测试
- *
- * @param age
- * 年龄条件
- * @return 满足要求的职工信息集合
- * @date 2019/6/4 21:55
- */
- List<StaffPO> queryDemo(Integer age);
- }
ShardingServiceImpl业务实现:
- import com.aspire.shardingdatabasetable.mapper.ShardingMapper;
- import com.aspire.shardingdatabasetable.model.StaffPO;
- import com.aspire.shardingdatabasetable.service.ShardingService;
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.stereotype.Service;
- import org.springframework.transaction.annotation.Transactional;
-
- import java.util.List;
-
- /**
- * 业务逻辑层
- *
- * @author JustryDeng
- * @date 2019/5/29 17:35
- */
- @Slf4j
- @Service
- public class ShardingServiceImpl implements ShardingService {
-
- private final ShardingMapper shardingMapper;
-
- public ShardingServiceImpl(ShardingMapper shardingMapper) {
- this.shardingMapper = shardingMapper;
- }
-
- @Override
- @Transactional(rollbackFor = {Exception.class})
- public int insertDemo(StaffPO staffPO) {
- log.info("got into ShardingServiceImpl -> insertDemo, param is -> {}", staffPO);
- return shardingMapper.insertData(staffPO);
- }
-
- @Override
- public List<StaffPO> queryDemo(Integer age) {
- log.info("got into ShardingServiceImpl -> queryDemo, param is -> {}", age);
- return shardingMapper.queryStaffByAge(age);
- }
- }
ShardingMapper数据操作层:
- import com.aspire.shardingdatabasetable.model.StaffPO;
- 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 java.util.List;
-
- /**
- * 持久层
- *
- * @author JustryDeng
- * @date 2019/5/29 17:36
- */
- @Mapper
- public interface ShardingMapper {
-
- /**
- * 向逻辑表staff中插入数据
- *
- * @param staffPO
- * 职工模型
- * @return 受影响行数
- * @date 2019/6/3 23:38
- */
- @Insert({"insert into staff (`id`, `age`, `name`, `gender`) values (#{staffPO.id},",
- " #{staffPO.age}, #{staffPO.name}, #{staffPO.gender})"})
- int insertData(@Param("staffPO") StaffPO staffPO);
-
- /**
- * 根据年龄大于等于给定age的职工信息
- *
- * @param age
- * 年龄条件
- * @return 符合要求的职工集合
- * @date 2019/6/4 21:52
- */
- @Select("select id, name, age, gender from staff where age >= #{age}")
- List<StaffPO> queryStaffByAge(Integer age);
- }
- import com.aspire.shardingdatabasetable.model.StaffPO;
- import com.aspire.shardingdatabasetable.service.ShardingService;
- import org.junit.Assert;
- 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.util.List;
- import java.util.UUID;
-
- @RunWith(SpringRunner.class)
- @SpringBootTest
- public class ShardingDatabaseTableApplicationTests {
-
- @Autowired
- ShardingService shardingService;
-
- @Test
- public void allTest() {
- oneTest();
- twoTest();
- threeTest();
- fourTest();
- fiveTest();
- sixTest();
- }
-
- @Test
- public void oneTest() {
- String uuid = UUID.randomUUID().toString();
- StaffPO staffPO = StaffPO.builder()
- .id(uuid)
- .name("邓沙利文")
- .age(25)
- .gender("男")
- .build();
- int result = shardingService.insertDemo(staffPO);
- Assert.assertEquals(1, result);
- }
-
- @Test
- public void twoTest() {
- String uuid = UUID.randomUUID().toString();
- StaffPO staffPO = StaffPO.builder()
- .id(uuid)
- .name("疯一般的女子")
- .age(123)
- .gender("女")
- .build();
- int result = shardingService.insertDemo(staffPO);
- Assert.assertEquals(1, result);
- }
-
- @Test
- public void threeTest() {
- String uuid = UUID.randomUUID().toString();
- StaffPO staffPO = StaffPO.builder()
- .id(uuid)
- .name("无敌小婷妹")
- .age(21)
- .gender("女")
- .build();
- int result = shardingService.insertDemo(staffPO);
- Assert.assertEquals(1, result);
- }
-
- @Test
- public void fourTest() {
- String uuid = UUID.randomUUID().toString();
- StaffPO staffPO = StaffPO.builder()
- .id(uuid)
- .name("邓~")
- .age(125)
- .gender("男")
- .build();
- int result = shardingService.insertDemo(staffPO);
- Assert.assertEquals(1, result);
- }
-
- @Test
- public void fiveTest() {
- String uuid = UUID.randomUUID().toString();
- StaffPO staffPO = StaffPO.builder()
- .id(uuid)
- .name("亨得帅")
- .age(66)
- .gender("男")
- .build();
- int result = shardingService.insertDemo(staffPO);
- Assert.assertEquals(1, result);
- }
-
- @Test
- public void sixTest() {
- String uuid = UUID.randomUUID().toString();
- StaffPO staffPO = StaffPO.builder()
- .id(uuid)
- .name("小聋女")
- .age(80)
- .gender("女")
- .build();
- int result = shardingService.insertDemo(staffPO);
- Assert.assertEquals(1, result);
- }
-
- @Test
- public void qeuryTest() {
- List<StaffPO> result = shardingService.queryDemo(10);
- for (StaffPO staffPO : result) {
- System.out.println(staffPO);
- }
- }
- }
插入测试:运行allTest方法后,控制台输出:
- . ____ _ __ _ _
- /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
- ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
- \\/ ___)| |_)| | | | | || (_| | ) ) ) )
- ' |____| .__|_| |_|_| |_\__, | / / / /
- =========|_|==============|___/=/_/_/_/
- :: Spring Boot :: (v2.1.4.RELEASE)
-
- 23:56:49.904 [main] INFO Sharding-JDBC-SQL:59- Logic SQL: insert into staff (`id`, `age`, `name`, `gender`) values (?, ?, ?, ?)
- 23:56:49.906 [main] INFO Sharding-JDBC-SQL:59- SQLStatement: InsertStatement(columns=[Column(name=id, tableName=staff), Column(name=age, tableName=staff), Column(name=name, tableName=staff), Column(name=gender, tableName=staff)], multipleConditions=[], columnsListLastPosition=48, generateKeyColumnIndex=-1, afterValuesPosition=57, valuesListLastPosition=69, generatedKey=null)
- 23:56:49.906 [main] INFO Sharding-JDBC-SQL:59- Actual SQL: youngerDb ::: insert into staff_man (`id`, `age`, `name`, `gender`) values (?, ?, ?, ?) ::: [2c757252-3779-4d0f-b70f-db272f12b091, 25, 邓沙利文, 男]
- 23:56:50.116 [main] INFO Sharding-JDBC-SQL:59- Logic SQL: insert into staff (`id`, `age`, `name`, `gender`) values (?, ?, ?, ?)
- 23:56:50.116 [main] INFO Sharding-JDBC-SQL:59- SQLStatement: InsertStatement(columns=[Column(name=id, tableName=staff), Column(name=age, tableName=staff), Column(name=name, tableName=staff), Column(name=gender, tableName=staff)], multipleConditions=[], columnsListLastPosition=48, generateKeyColumnIndex=-1, afterValuesPosition=57, valuesListLastPosition=69, generatedKey=null)
- 23:56:50.116 [main] INFO Sharding-JDBC-SQL:59- Actual SQL: otherDb ::: insert into staff (`id`, `age`, `name`, `gender`) values (?, ?, ?, ?) ::: [5a6ed073-5891-482f-ba1e-959f4e832cfd, 123, 疯一般的女子, 女]
- 23:56:50.149 [main] INFO Sharding-JDBC-SQL:59- Logic SQL: insert into staff (`id`, `age`, `name`, `gender`) values (?, ?, ?, ?)
- 23:56:50.150 [main] INFO Sharding-JDBC-SQL:59- SQLStatement: InsertStatement(columns=[Column(name=id, tableName=staff), Column(name=age, tableName=staff), Column(name=name, tableName=staff), Column(name=gender, tableName=staff)], multipleConditions=[], columnsListLastPosition=48, generateKeyColumnIndex=-1, afterValuesPosition=57, valuesListLastPosition=69, generatedKey=null)
- 23:56:50.150 [main] INFO Sharding-JDBC-SQL:59- Actual SQL: youngerDb ::: insert into staff_woman (`id`, `age`, `name`, `gender`) values (?, ?, ?, ?) ::: [3d0aadf3-94e2-4ee8-9715-421fd8f4bc9d, 21, 无敌小婷妹, 女]
- 23:56:50.208 [main] INFO Sharding-JDBC-SQL:59- Logic SQL: insert into staff (`id`, `age`, `name`, `gender`) values (?, ?, ?, ?)
- 23:56:50.209 [main] INFO Sharding-JDBC-SQL:59- SQLStatement: InsertStatement(columns=[Column(name=id, tableName=staff), Column(name=age, tableName=staff), Column(name=name, tableName=staff), Column(name=gender, tableName=staff)], multipleConditions=[], columnsListLastPosition=48, generateKeyColumnIndex=-1, afterValuesPosition=57, valuesListLastPosition=69, generatedKey=null)
- 23:56:50.209 [main] INFO Sharding-JDBC-SQL:59- Actual SQL: otherDb ::: insert into staff (`id`, `age`, `name`, `gender`) values (?, ?, ?, ?) ::: [c1cde34f-3093-4296-ac57-bef30f7b4777, 125, 邓~, 男]
- 23:56:50.302 [main] INFO Sharding-JDBC-SQL:59- Logic SQL: insert into staff (`id`, `age`, `name`, `gender`) values (?, ?, ?, ?)
- 23:56:50.302 [main] INFO Sharding-JDBC-SQL:59- SQLStatement: InsertStatement(columns=[Column(name=id, tableName=staff), Column(name=age, tableName=staff), Column(name=name, tableName=staff), Column(name=gender, tableName=staff)], multipleConditions=[], columnsListLastPosition=48, generateKeyColumnIndex=-1, afterValuesPosition=57, valuesListLastPosition=69, generatedKey=null)
- 23:56:50.302 [main] INFO Sharding-JDBC-SQL:59- Actual SQL: olderDb ::: insert into staff_man (`id`, `age`, `name`, `gender`) values (?, ?, ?, ?) ::: [29c8165f-ba9f-4aad-bb27-552026840ca4, 66, 亨得帅, 男]
- 23:56:50.374 [main] INFO Sharding-JDBC-SQL:59- Logic SQL: insert into staff (`id`, `age`, `name`, `gender`) values (?, ?, ?, ?)
- 23:56:50.375 [main] INFO Sharding-JDBC-SQL:59- SQLStatement: InsertStatement(columns=[Column(name=id, tableName=staff), Column(name=age, tableName=staff), Column(name=name, tableName=staff), Column(name=gender, tableName=staff)], multipleConditions=[], columnsListLastPosition=48, generateKeyColumnIndex=-1, afterValuesPosition=57, valuesListLastPosition=69, generatedKey=null)
- 23:56:50.375 [main] INFO Sharding-JDBC-SQL:59- Actual SQL: olderDb ::: insert into staff_woman (`id`, `age`, `name`, `gender`) values (?, ?, ?, ?) ::: [3f0463a8-26bc-4cf2-8133-7878fda556e0, 80, 小聋女, 女]
打开库表,观察:
older库staff_man表:
older库staff_woman表:
younger库staff_man表:
younger库staff_woman表:
other库staff表:
可见分库分表成功!
查询测试:运行qeuryTest方法后,控制台输出:
查询也没问题!
ShardingSphere实现分库分表完毕!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。