# Sharding-JDBC從入門到精通(6)-- Sharding-JDBC 水平分庫 和 垂直分庫。

Sharding-JDBC從入門到精通(6)-- Sharding-JDBC 水平分庫 和 垂直分庫。

一、Sharding-JDBC 水平分庫-分片策略配置

1、分庫策略定義方式如下

# 分庫策略,如何將一個邏輯表映射到多個數據源
spring.shardingsphere.sharding.tables.<邏輯表名稱>.qatabase-strategy.<分片策略>.<分片策略屬性名>= #分片策略屬性值# 分表策略,如何將一個邏輯表映射為多個實際表
spring.shardingsphere.sharding.tables.<邏輯表名稱>.table-strategy.<分片策略>.<分片策略屬性名>= #分片策略屬性值# 分庫策略:以 user_id 為分片鍵,分片策略為 user_id % 2 + 1,user_id 為偶數操作 m1 數據源,否則操作 m2
spring.shardingsphere.sharding.tables.t_order.database-strategy.inline.sharding-column = user_id
spring.shardingsphere.sharding.tables.t_order.database-strategy.inline.algorithm-expression = m$->{user_id % 2 + 1}

2、分片規則修改:

由于數據庫需要拆分了兩個,這里需要配置兩個數據源。
分庫需要配置分庫的策略,和分表策略的意義類似,通過分庫策略實現數據操作針對分庫的數據庫進行操作。

# 配置 sharding-jdbc 分片規則(2024-6-29 分片規則修改)
# 定義數據源(定義 多個 數據源名為 m1, m2)
spring.shardingsphere.datasource.names = m1,m2spring.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_1?useUnicode=true
spring.shardingsphere.datasource.m1.username = root
spring.shardingsphere.datasource.m1.password = 12311spring.shardingsphere.datasource.m2.type = com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m2.driver-class-name = com.mysql.jdbc.Driver
spring.shardingsphere.datasource.m2.url = jdbc:mysql://localhost:3306/order_db_2?useUnicode=true
spring.shardingsphere.datasource.m2.username = root
spring.shardingsphere.datasource.m2.password = 12311

3、在 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 分片規則(2024-6-29 分片規則修改)
# 定義數據源(定義 多個 數據源名為 m1, m2)
spring.shardingsphere.datasource.names = m1,m2spring.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_1?useUnicode=true
spring.shardingsphere.datasource.m1.username = root
spring.shardingsphere.datasource.m1.password = 12311spring.shardingsphere.datasource.m2.type = com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m2.driver-class-name = com.mysql.jdbc.Driver
spring.shardingsphere.datasource.m2.url = jdbc:mysql://localhost:3306/order_db_2?useUnicode=true
spring.shardingsphere.datasource.m2.username = root
spring.shardingsphere.datasource.m2.password = 12311# 分庫策略:以 user_id 為分片鍵,分片策略為 user_id % 2 + 1,user_id 為偶數操作 m1 數據源,否則操作 m2
spring.shardingsphere.sharding.tables.t_order.database-strategy.inline.sharding-column = user_id
spring.shardingsphere.sharding.tables.t_order.database-strategy.inline.algorithm-expression = m$->{user_id % 2 + 1}# 指定 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

4、Sharding-JDBC 支持以下幾種分片策略:

不管理分庫還是分表,策略基本一樣。

  • standard: 標準分片策略,對應 Standardshardingstrategy。提供對 SQL 語句中的 =,IN 和 BETWEEN AND 的分片操作支持。StandardShardingStrategy 只支持單分片鍵,提供 PreciseShardingAlgorithm 和 RangeShardingAlgorithm 兩個分片算法。PreciseShardingAlgorithm 是必選的,用于處理 = 和 IN 的分片。RangeShardingAlgorithm 是可選的,用于處理 BETWEEN AND 分片,如果不配置 RangeshardingAlgorithm,SQL 中的 BETWEEN AND 將按照全庫路由處理。

  • complex: 符合分片策略,對應 ComplexshardingStrategy。復合分片策略。提供對 SQL 語句中的 =,IN 和 BETWEEN AND 的分片操作支持。ComplexshardingStrategy 支持多分片鍵,由于多分片鍵之間的關系復雜因此并未進行過多的封裝,而是直接將分片鍵值組合以及分片操作符透傳至分片算法,完全由應用開發者實現,提供最大的靈活度。

  • inline: 行表達式分片策略,對應 InlineshardingStrategy。使用 Groovy 的表達式,提供對 SQL 語句中的 = 和 IN 的分片操作支持,只支持單分片鍵。對于簡單的分片算法,可以通過簡單的配置使用,從而避免繁瑣的 Java 代碼開發,如:t_user_$->{u id % 8} 表示 t_user 表根據u_id 模8,而分成8張表,表名稱為 t_user_0 到 t_user_7。

  • hint: Hint 分片策略,對應 HintShardingStrategy。通過 Hint 而非 SQL 解析的方式分片的策略。對于分片字段非 SQL決 定,而由其他外置條件決定的場景,可使用 SQLHint 靈活的注入分片字段。例:內部系統,按照員工登錄主鍵分庫,而數據庫中并無此字段。SQL Hint 支持通過 Java API 和 SQL 注釋(待實現)兩種方式使用。

  • none : 不分片策略,對應 NoneShardingStrategy。不分片的策略。

5、創建兩個數據庫:order_db_1, order_db_2

CREATE DATABASE `order_db_1` CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';
CREATE DATABASE `order_db_2` CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';

6、在 order_db_1, order_db_2 中分別 創建 t_order_1 和 t_order_2 兩個表:


# 在 數據庫 order_db_1 中,創建兩張表。USE `order_db_1`;# 創建  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;

# 在 數據庫 order_db_2 中,創建兩張表。USE `order_db_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;

二、Sharding-JDBC 水平分庫-插入訂單

1、在 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 分片規則(2024-6-29 分片規則修改)
# 定義數據源(定義 多個 數據源名為 m1, m2)
spring.shardingsphere.datasource.names = m1,m2spring.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_1?useUnicode=true
spring.shardingsphere.datasource.m1.username = root
spring.shardingsphere.datasource.m1.password = 12311spring.shardingsphere.datasource.m2.type = com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m2.driver-class-name = com.mysql.jdbc.Driver
spring.shardingsphere.datasource.m2.url = jdbc:mysql://localhost:3306/order_db_2?useUnicode=true
spring.shardingsphere.datasource.m2.username = root
spring.shardingsphere.datasource.m2.password = 12311# 分庫策略:以 user_id 為分片鍵,分片策略為 user_id % 2 + 1,user_id 為偶數操作 m1 數據源,否則操作 m2
spring.shardingsphere.sharding.tables.t_order.database-strategy.inline.sharding-column = user_id
spring.shardingsphere.sharding.tables.t_order.database-strategy.inline.algorithm-expression = m$->{user_id % 2 + 1}# 指定 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

2、在 sharding_jdbc_simple 子工程(子模塊)中,測試類 OrderDao 的測試類 OrderDaoTest.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;@Test  //查詢public void testSelectOrderByIds(){List<Long> ids = new ArrayList<>();ids.add(1013467489922711552L);  //此order_id 在 mysql 數據庫的 t_order_1 表中,ids.add(1013465458055053313L);  //此order_id 在 mysql 數據庫的 t_order_2 表中,List<Map> maps = orderDao.selectOrderByIds(ids);System.out.println(maps);}@Test  //插入數據public void testInsertOrder(){
//            // 1)此數據會插入到 m1 數據庫: 1L % 2 + 1 = 2 得到 M2,由此可得 向 order_db_2 數據庫中插入 20 條數據。
//            orderDao.insertOrder(new BigDecimal(i ),1L, "success2");// 2)此數據會插入到 m1 數據庫: 4L % 2 + 1 = 1 得到 M1,由此可得 向 order_db_1 數據庫中插入 20 條數據。for(int i=1; i<20; i++){orderDao.insertOrder(new BigDecimal(i ),4L, "success2");}}
}

3、運行測試類 OrderDaoTest.java 插入數據 testInsertOrder 方法,進行測試。

1)1L % 2 + 1 = 2 得到 M2,由此可得 向 t_order_2 數據庫中插入 20 條數據。
2)此數據會插入到 m1 數據庫: 4L % 2 + 1 = 1 得到 M1,由此可得 向 order_db_1 數據庫中插入 10 條數據。

插入數據.png

三、Sharding-JDBC 水平分庫-查詢訂單

1、在 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 分片規則(2024-6-29 分片規則修改)
# 定義數據源(定義 多個 數據源名為 m1, m2)
spring.shardingsphere.datasource.names = m1,m2spring.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_1?useUnicode=true
spring.shardingsphere.datasource.m1.username = root
spring.shardingsphere.datasource.m1.password = 12311spring.shardingsphere.datasource.m2.type = com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m2.driver-class-name = com.mysql.jdbc.Driver
spring.shardingsphere.datasource.m2.url = jdbc:mysql://localhost:3306/order_db_2?useUnicode=true
spring.shardingsphere.datasource.m2.username = root
spring.shardingsphere.datasource.m2.password = 12311# 分庫策略:以 user_id 為分片鍵,分片策略為 user_id % 2 + 1,user_id 為偶數操作 m1 數據源,否則操作 m2
spring.shardingsphere.sharding.tables.t_order.database-strategy.inline.sharding-column = user_id
spring.shardingsphere.sharding.tables.t_order.database-strategy.inline.algorithm-expression = m$->{user_id % 2 + 1}# 指定 t_order 表的數據分布情況,配置數據節點(t_order 映射到 t_order_1 或者 t_order_2): 只能路由到 m1 數據庫
#spring.shardingsphere.sharding.tables.t_order.actual-data-nodes = m1.t_order_$->{1..2}
# 指定 t_order 表的數據分布情況,配置數據節點(t_order 映射到 t_order_1 或者 t_order_2): 動態路由到 m1 數據庫 或 m2 數據庫。spring.shardingsphere.sharding.tables.t_order.actual-data-nodes = m$->{1..2}.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

2、在 sharding_jdbc_simple 子工程(子模塊)中,修改 dao 接口類 OrderDao.java 添加 //查詢數據:根據訂單ID 和 用戶 id 查詢訂單 方法。

/***   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 和 用戶 id 查詢訂單// ( SELECT * FROM t_order_1 WHERE user_id = 4 AND order_id IN (1014650592712196096, 1014650593467170816); )@Select( "<script>" +"select" +" * " +" from t_order t " +" where t.order_id in " +" <foreach collection=' orderIds' open='(' separator=',' close=')' item='id'>" +" #{id} " +" </foreach>" +" and user_id = ${userId}" +"</script>" )List<Map> selectOrderByIdsAndUserId(@Param("userId") Long userId, @Param("orderIds") List<Long> orderIds);//查詢數據:根據訂單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);
}

3、在 sharding_jdbc_simple 子工程(子模塊)中,修改 測試類 OrderDao 的測試類 查詢方法,進行多次查詢測試。添加 根據訂單ID 和 用戶 id 查詢訂單 的方法。

/***   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;@Test  //查詢--根據訂單ID 和 用戶 id 查詢訂單public void testSelectOrderByIdsAndUserId(){List<Long> ids = new ArrayList<>();// 水平分庫測試如下:List<Long> ids2 = new ArrayList<>();//        //1)查詢不存在的 order_id(在 m1 或 m2 中,都不存在),添加了 userId , 會輸出真實的2條SQL語句。
//        ids2.add(1013467489922711552L);  //此 order_id 在 mysql 的 m1 和 m2 數據庫中 的 t_order_1 表 和 t_order_2 表中 都不存在
//        ids2.add(1013465458055053313L);  //此 order_id 在 mysql 的 m1 和 m2 數據庫中 的 t_order_1 表 和 t_order_2 表中 都不存在
//        List<Map> maps = orderDao.selectOrderByIdsAndUserId(4L, ids2);
//        System.out.println(maps);//2)查詢存在的 order_id(一條在 m1 數據庫,一條在 m2 數據庫中),添加了 userId , 會輸出真實的2條SQL語句。ids2.add(1014650592712196096L);  //此 order_id 在 mysql 的 m1 數據庫中 t_order_1 表 中。ids2.add(1014635737775079425L);  //此 order_id 在 mysql 的 m2 數據庫中 t_order_2 表 中。List<Map> maps2 = orderDao.selectOrderByIdsAndUserId(4L, ids2);System.out.println(maps2);}@Test  //查詢public void testSelectOrderByIds(){List<Long> ids = new ArrayList<>();//        //查詢數據庫 order_db 中的數據 order_id(水平分表)
//        ids.add(1013467489922711552L);  //此order_id 在 mysql 數據庫的 t_order_1 表中,
//        ids.add(1013465458055053313L);  //此order_id 在 mysql 數據庫的 t_order_2 表中,
//        List<Map> maps = orderDao.selectOrderByIds(ids);
//        System.out.println(maps);// 水平分庫測試如下:List<Long> ids2 = new ArrayList<>();//1)查詢不存在的 order_id(在 m1 或 m2 中,都不存在),會輸出真實的4條SQL語句。ids2.add(1013467489922711552L);  //此 order_id 在 mysql 的 m1 和 m2 數據庫中 的 t_order_1 表 和 t_order_2 表中 都不存在ids2.add(1013465458055053313L);  //此 order_id 在 mysql 的 m1 和 m2 數據庫中 的 t_order_1 表 和 t_order_2 表中 都不存在List<Map> maps = orderDao.selectOrderByIds(ids2);System.out.println(maps);//        //2)查詢存在的 order_id(一條在 m1 數據庫,一條在 m2 數據庫中),會輸出真實的4條SQL語句。
//        ids2.add(1014650592712196096L);  //此 order_id 在 mysql 的 m1 數據庫中 t_order_1 表 中。
//        ids2.add(1014635737775079425L);  //此 order_id 在 mysql 的 m2 數據庫中 t_order_2 表 中。
//        List<Map> maps2 = orderDao.selectOrderByIds(ids2);
//        System.out.println(maps2);//        //3)查詢存在的 order_id(2條都在 m1 數據庫,不同表中),會輸出真實的4條SQL語句。
//        ids2.add(1014650592712196096L);  //此 order_id 在 mysql 的 m1 數據庫中 t_order_1 表 中。
//        ids2.add(1014635737775079425L);  //此 order_id 在 mysql 的 m1 數據庫中 t_order_2 表 中。
//        List<Map> maps2 = orderDao.selectOrderByIds(ids2);
//        System.out.println(maps2);//        //4)查詢存在的 order_id(2條都在 m1 數據庫,同一表中),會輸出真實的2條SQL語句。
//        ids2.add(1014650592712196096L);  //此 order_id 在 mysql 的 m1 數據庫中 t_order_1 表 中。
//        ids2.add(1014635742883741696L);  //此 order_id 在 mysql 的 m1 數據庫中 t_order_1 表 中。
//        List<Map> maps2 = orderDao.selectOrderByIds(ids2);
//        System.out.println(maps2);//        //5)查詢存在的 order_id(1條都在 m2 數據庫),會輸出真實的2條SQL語句。
//        ids2.add(1014635741851942912L);  //此 order_id 在 mysql 的 m2 數據庫中 t_order_1 表 中。
//        List<Map> maps2 = orderDao.selectOrderByIds(ids2);
//        System.out.println(maps2);}@Test  //插入數據public void testInsertOrder(){//orderDao.insertOrder(new BigDecimal(11 ),1L, "SUCCESS");for(int i=1; i<10; i++){
//            // 1)此數據會插入到 m1 數據庫: 1L % 2 + 1 = 2 得到 M2,由此可得 向 order_db_2 數據庫中插入 20 條數據。
//            orderDao.insertOrder(new BigDecimal(i ),1L, "success2");// 2)此數據會插入到 m1 數據庫: 4L % 2 + 1 = 1 得到 M1,由此可得 向 order_db_1 數據庫中插入 10 條數據。orderDao.insertOrder(new BigDecimal(i ),4L, "success3");}}
}

4、運行測試類 OrderDaoTest.java 查詢數據 testSelectOrderByIds 方法,進行測試。

1)查詢不存在的 order_id(在 m1 或 m2 中,都不存在),會輸出真實的4條SQL語句。

查詢數據1.png

2)查詢存在的 order_id(一條在 m1 數據庫,一條在 m2 數據庫中),會輸出真實的4條SQL語句。

查詢數據2.png

3)查詢存在的 order_id(2條都在 m1 數據庫,不同表中),會輸出真實的4條SQL語句。

查詢數據3.png

4)查詢存在的 order_id(2條都在 m1 數據庫 同一表中),會輸出真實的2條SQL語句。

查詢數據4.png

5)查詢存在的 order_id(1條都在 m2 數據庫),會輸出真實的2條SQL語句。

查詢數據5.png

6)查詢不存在的 order_id(在 m1 或 m2 中,都不存在),添加了 userId ,

查詢數據6.png

7)查詢存在的 order_id(一條在 m1 數據庫,一條在 m2 數據庫中),添加了 userId , 會輸出真實的2條SQL語句。

查詢數據7.png

四、Sharding-JDBC 垂直分庫-分片策略配置

1、創建數據庫:user_db

CREATE DATABASE `user_db` CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';

2、在 suer_db 中分別 創建 t_user 表:


# 在 數據庫 order_db_1 中,創建兩張表。USE `user_db`;# 創建  t_user 表DROP TABLE IF EXISTS `t_user`;CREATE TABLE `t_user` (
`user_id` BIGINT(20) NOT NULL COMMENT '用戶id',
`fullname` VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '用戶姓名',
`user_type` char(1) DEFAULT NULL COMMENT '用戶類型', 
PRIMARY KEY(`user_id`) USING BTREE
) ENGINE = INNODB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

3、在 application.properties 配置文件中,配置數據源,

spring.shardingsphere.datasource.names = m0,m1,m2spring.shardingsphere.datasource.m0.type = com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m0.driver-class-name = com.mysql.jdbc.Driver
spring.shardingsphere.datasource.m0.url = jdbc:mysql://localhost:3306/user_db?useUnicode=true
spring.shardingsphere.datasource.m0.username = root
spring.shardingsphere.datasource.m0.password = 12311# 分庫策略:以 user_id 為分片鍵,分片策略為 user_id % 2 + 1,user_id 為偶數操作 m1 數據源,否則操作 m2
spring.shardingsphere.sharding.tables.t_order.database-strategy.inline.sharding-column = user_id
spring.shardingsphere.sharding.tables.t_order.database-strategy.inline.algorithm-expression = m$->{user_id % 2 + 1}# 配置 user_db 數據節點
spring.shardingsphere.sharding.tables.t_user.actual-data-nodes = m0.t_user# 指定 t_user 表的分片策略,分片策略包括分片鍵和分片算法(未分庫分表也需要配置)
spring.shardingsphere.sharding.tables.t_user.table-strategy.inline.sharding-column = user_id
spring.shardingsphere.sharding.tables.t_user.table-strategy.inline.algorithm-expression = t_user

五、Sharding-JDBC 垂直分庫-插入和查詢測試

1、在 sharding_jdbc_simple 子工程(子模塊)中,修改 application.properties 配置文件,添加 user_db 數據庫的 配置分庫分表策略。

#  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 分片規則(2024-6-29 分片規則修改)
# 定義數據源(定義 多個 數據源名為 m1, m2)
spring.shardingsphere.datasource.names = m0,m1,m2spring.shardingsphere.datasource.m0.type = com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m0.driver-class-name = com.mysql.jdbc.Driver
spring.shardingsphere.datasource.m0.url = jdbc:mysql://localhost:3306/user_db?useUnicode=true
spring.shardingsphere.datasource.m0.username = root
spring.shardingsphere.datasource.m0.password = 12311spring.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_1?useUnicode=true
spring.shardingsphere.datasource.m1.username = root
spring.shardingsphere.datasource.m1.password = 12311spring.shardingsphere.datasource.m2.type = com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m2.driver-class-name = com.mysql.jdbc.Driver
spring.shardingsphere.datasource.m2.url = jdbc:mysql://localhost:3306/order_db_2?useUnicode=true
spring.shardingsphere.datasource.m2.username = root
spring.shardingsphere.datasource.m2.password = 12311# 分庫策略:以 user_id 為分片鍵,分片策略為 user_id % 2 + 1,user_id 為偶數操作 m1 數據源,否則操作 m2
spring.shardingsphere.sharding.tables.t_order.database-strategy.inline.sharding-column = user_id
spring.shardingsphere.sharding.tables.t_order.database-strategy.inline.algorithm-expression = m$->{user_id % 2 + 1}# 指定 t_order 表的數據分布情況,配置數據節點(t_order 映射到 t_order_1 或者 t_order_2): 只能路由到 m1 數據庫
#spring.shardingsphere.sharding.tables.t_order.actual-data-nodes = m1.t_order_$->{1..2}
# 指定 t_order 表的數據分布情況,配置數據節點(t_order 映射到 t_order_1 或者 t_order_2): 動態路由到 m1 數據庫 或 m2 數據庫。
spring.shardingsphere.sharding.tables.t_order.actual-data-nodes = m$->{1..2}.t_order_$->{1..2}
# 配置 user_db 數據節點
spring.shardingsphere.sharding.tables.t_user.actual-data-nodes = m$->{0}.t_user# 指定 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}# 指定 t_user 表的分片策略,分片策略包括分片鍵和分片算法(未分庫分表也需要配置)
spring.shardingsphere.sharding.tables.t_user.table-strategy.inline.sharding-column = user_id
spring.shardingsphere.sharding.tables.t_user.table-strategy.inline.algorithm-expression = t_user# 打開 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

2、在 sharding_jdbc_simple 子工程(子模塊)中,創建 接口類 UserDao.java

/***   dbsharding\sharding_jdbc_simple\src\main\java\djh\it\dbsharding\simple\dao\UserDao.java**   2024-7-1 創建 接口類 UserDao.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.util.List;
import java.util.Map;@Mapper
@Component
public interface UserDao {//新增用戶@Insert("insert into t_user(user_id, fullname) value(#{userId}, #{fullname})")int insertUser(@Param("userId") Long userId, @Param("fullname") String fullname);//根據id列表查詢多個用戶@Select({ "<script>" ," select" ," * " ," from t_user t " ," where t.user_id in "," <foreach collection=' userIds' open='(' separator=',' close=')' item='id'>" +" #{id} " ," </foreach>" ,"</script>" })List<Map> selectUserId(@Param("userIds") List<Long> userIds);
}

3、在 sharding_jdbc_simple 子工程(子模塊)中,創建 接口類 UserDao.java 的測試類 UserDaoTest.java 進行插入數據 和 查詢數據測試。

/***   dbsharding\sharding_jdbc_simple\src\test\java\djh\it\dbsharding\simple\dao\UserDaoTest.java**   2024-7-1 創建 接口類 UserDao.java 的測試類 UserDaoTest.java 進行插入數據 和 查詢數據測試 UserDaoTest.java*/
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.util.ArrayList;
import java.util.List;
import java.util.Map;@RunWith(SpringRunner.class)
@SpringBootTest(classes = {ShardingJdbcSimpleBootstrap.class})
public class UserDaoTest {@AutowiredUserDao userDao;@Testpublic void testInsertUser() {for(int i=0; i<10; i++){Long id = i + 1L;userDao.insertUser(id, "姓名" + id);}}@Testpublic void testSelectUserByIds() {List<Long> userIds = new ArrayList<>();userIds.add(1L);userIds.add(2L);List<Map> users = userDao.selectUserId(userIds);System.out.println(users);}
}

4、運行測試類 UserDaoTest.java,查看結果。

Sharding-JDBC垂直分庫-插入和查詢測試.png

在這里插入圖片描述

上一節關聯鏈接請點擊
# Sharding-JDBC從入門到精通(5)-- Sharding-JDBC 執行原理

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/40553.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/40553.shtml
英文地址,請注明出處:http://en.pswp.cn/web/40553.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

第33集《大乘起信論》

《大乘起信論》和尚尼慈悲&#xff0c;諸位法師、諸位居士&#xff0c;阿彌陀佛&#xff01;&#xff08;阿彌陀佛&#xff01;&#xff09;請大家打開《講義》第七十四頁&#xff0c;子二、釋觀。 本論的特色&#xff0c;一言以蔽之就是文簡意賅、辭約理富&#xff0c;就是說…

VUE2拖拽組件:vue-draggable-resizable-gorkys

vue-draggable-resizable-gorkys組件基于vue-draggable-resizable進行二次開發, 用于可調整大小和可拖動元素的組件并支持沖突檢測、元素吸附、元素對齊、輔助線 安裝: npm install --save vue-draggable-resizable-gorkys 全局引用: import Vue from vue import vdr fro…

嵌入式linux面試1

1. linux 1.1. Window系統和Linux系統的區別 linux區分大小寫windows在dos&#xff08;磁盤操作系統&#xff09;界面命令下不區分大小寫&#xff1b; 1.2. 文件格式區分 windows用擴展名區分文件&#xff1b;如.exe代表執行文件&#xff0c;.txt代表文本文件&#xff0c;.…

運用Python與Keras框架打造深度學習圖像分類應用:詳盡步驟與代碼實例解析

引言 隨著深度學習技術的飛速發展&#xff0c;其在圖像識別和分類領域的應用日益廣泛。在這一背景下&#xff0c;Python因其豐富的數據科學庫和強大的生態系統而成為首選編程語言之一。在本文中&#xff0c;我們將深入探討如何使用Python和其中的Keras深度學習框架來完成一個實…

手動將dingtalk-sdk-java jar包打入maven本地倉庫

有時候,中央鏡像庫不一定有自己需要的jar包,這時候我們就需要用到該方法,將jar打入maven本地倉庫,然后項目中,正常使用maven的引入規則。 mvn install:install-file -Dmaven.repo.local=D:\software\maven\apache-maven-3.6.3-bin\apache-maven-3.6.3\repo -DgroupId=ding…

學習筆記——交通安全分析11

目錄 前言 當天學習筆記整理 4信控交叉口交通安全分析 結束語 前言 #隨著上一輪SPSS學習完成之后&#xff0c;本人又開始了新教材《交通安全分析》的學習 #整理過程不易&#xff0c;喜歡UP就點個免費的關注趴 #本期內容接上一期10筆記 #最近確實太懶了&#xff0c;接受…

跨越數據邊界:域適應在目標檢測中的革新作用

標題&#xff1a;跨越數據邊界&#xff1a;域適應在目標檢測中的革新作用 在機器學習和計算機視覺領域&#xff0c;尤其是目標檢測任務中&#xff0c;域適應&#xff08;Domain Adaptation&#xff09;是一種關鍵技術&#xff0c;它解決了模型在不同數據分布上的泛化問題。當訓…

C語言字節對齊技術在嵌入式、網絡與操作系統中的應用與優化

第一部分&#xff1a;嵌入式系統中的字節對齊 嵌入式系統通常對性能和資源有著嚴格的要求。在這些系統中&#xff0c;字節對齊的正確使用可以顯著提高數據訪問速度&#xff0c;減少內存占用&#xff0c;并提高系統的整體效率。 一、嵌入式系統中的字節對齊挑戰 嵌入式系統中…

Caffeinated for Mac v2.0.6 Mac防休眠應用 兼容 M1/M2/M3

Caffeinated 可以防止您的 Mac 進入休眠狀態、屏幕變暗或者啟動屏幕保護。 應用介紹 您的屏幕是否總是在您不希望的時候變暗&#xff1f;那么Caffeinated就是您解決這個大麻煩的最好工具啦。Caffeinated是在Caffeine這個非常便捷、有用的工具的基礎上開發而來的。Caffeinated…

215. 數組中的第K個最大元素(中等)

215. 數組中的第K個最大元素 1. 題目描述2.詳細題解3.代碼實現3.1 Python3.2 Java 1. 題目描述 題目中轉&#xff1a;215. 數組中的第K個最大元素 2.詳細題解 快速排序算法在每一輪排序中&#xff0c;隨機選擇一個數字 x x x&#xff0c;根據與 x x x的大小關系將要排序的數…

PMP–知識卡片--PDCA循環

記憶 PDCA&#xff1a;計劃執行檢查調整&#xff0c;計劃觀察動作&#xff1b;plan do check action 定義 PDCA循環的含義是將質量管理分為四個過程&#xff0c;即計劃&#xff08;Plan&#xff09;、執行&#xff08;Do&#xff09;、檢查&#xff08;Check&#xff09;、處…

C++開發調試工具:GDB調試,windebug調試,adb調試

我們在C開發過程中時常避免不了要調試追蹤&#xff0c;一下介紹最主流的三種調試工具&#xff1a; 一.GDB調試 1.coredump文件&#xff1a; coredump文件是程序異常時系統產生的錯誤日志文件&#xff0c;即核心轉儲文件&#xff1b; 編譯一個debug程序&#xff0c;必須是debu…

使用 OpenCV 和 Python 進行車道檢測和物體檢測(YOLO)

本項目旨在開發一個集車道檢測與物體檢測功能于一體的智能視覺分析系統&#xff0c;利用先進的計算機視覺技術和深度學習模型&#xff0c;實現實時的道路場景理解和目標識別。系統主要依托OpenCV這一強大的計算機視覺庫&#xff0c;以及Python作為編程語言&#xff0c;融合了車…

MySQL索引教程(01):創建索引

文章目錄 MySQL 創建索引索引介紹MySQL CREATE INDEX 語法MySQL 索引類型MySQL CREATE INDEX 實例結論 MySQL 創建索引 對于一個具有大量數據行的表&#xff0c;如果你根據某個查詢條件檢索數據時很慢&#xff0c;可能是因為你沒有在檢索條件相關的列上創建索引。 索引類似于…

FPC生產工藝全流程詳解

FPC生產制作繁瑣而且難度較大&#xff0c;與普通PCB比較&#xff0c;FPC單位面積電路的造價高很多&#xff0c;但是&#xff0c;由于FPC優異的柔性、輕薄和可靠性等特性&#xff0c;給眾多領域的設備和產品提供了更廣泛的實現空間和新的設計方案&#xff0c;比如沉金板在電子、…

android的activty冷啟動和熱啟動差異是什么?

Android的Activity冷啟動和熱啟動之間存在顯著差異&#xff0c;這些差異主要體現在啟動過程、資源加載、組件初始化以及用戶體驗等方面。以下是對兩者差異的詳細分析&#xff1a; 一、定義與過程差異 冷啟動&#xff1a; 定義&#xff1a;冷啟動是指應用程序完全退出后&#…

Java需要英語基礎嗎?

Java編程語言本身并不要求必須有很強的英語基礎&#xff0c;因為Java的語法和邏輯是獨立于任何特定語言的。我收集歸類了一份嵌入式學習包&#xff0c;對于新手而言簡直不要太棒&#xff0c;里面包括了新手各個時期的學習方向編程教學、問題視頻講解、畢設800套和語言類教學&am…

android開發引入jar包

我在為一個安卓設備開發一個APP&#xff0c;設備的廠家給我提供了一個jar包&#xff0c;我應該如何把它引入到項目之中呢&#xff1f; 很慚愧我以前幾乎沒做過android的開發&#xff0c;在此之前這么一個簡單的問題也不會。 實踐 我隨手在Android studio中新建了一個項目。 你…

Java項目:基于SSM框架實現的共享客棧管理系統分前后臺【ssm+B/S架構+源碼+數據庫+畢業論文】

一、項目簡介 本項目是一套基于SSM框架實現的共享客棧管理系統 包含&#xff1a;項目源碼、數據庫腳本等&#xff0c;該項目附帶全部源碼可作為畢設使用。 項目都經過嚴格調試&#xff0c;eclipse或者idea 確保可以運行&#xff01; 該系統功能完善、界面美觀、操作簡單、功能…

Splunk Enterprise for Windows 未授權任意文件讀取漏洞復現(CVE-2024-36991)

0x01 產品簡介 Splunk Enterprise是一款功能強大的數據分析引擎,旨在從所有IT系統和基礎設施數據中提供數據搜索、報表和可視化展現。Splunk Enterprise能夠收集、索引和利用所有應用程序、服務器和設備(包括物理、虛擬和云中環境)生成的快速移動型計算機數據。它允許用戶從…