ShardingSphere-JDBC 使用手册
📄字数 10.1K
👁️阅读量 加载中...
本文将介绍如何使用 ShardingSphere-JDBC-4.1.1 快速搭建 SpringBoot 应用程序并连接 XuguDB,实现标准分片策略(standard)、行表达式分片策略(inline)、强制分片策略(Hint)。本文所展示项目中包含读写分离与非读写分离两种数据源场景,以下内容仅以非读写分离场景进行指导说明。
框架名称 | 适配起始版本 | 官网地址 | 源框架下载地址 | XuguDB框架下载 | demo程序地址 |
---|---|---|---|---|---|
ShardingSphere | 4.1.1 | ShardingSphere官网 | ShardingSphere源码 | 版本发布 | xugu-shardingsphere-demo |
提示
其他支持版本可详见版本发布列表
一、使用说明
1.1 下载 ShardingSphere 虚谷适配源码
访问虚谷数据库开放源代码仓库,选择所需版本分支。
图 1.1 shardingSphere仓库分支选择
下载当前分支源码zip文件
图 1.2 shardingSphere分支代码下载
1.2 安装 ShardingSphere 到本地 Maven 仓库
推荐使用 jdk 8 和 Maven 3.6.x 运行环境。
图 1.3 运行环境检查
在项目根目录下,使用maven命令
mvn clean install -DskipTests
安装适配源码到本地仓库,出现BUILD SUCCESS即执行成功。图 1.4 shardingSphere安装到本地maven仓库
二、连接示例
2.1 前提条件
- 计算机已安装 JDK 1.8 和 Maven。
- 计算机已安装 IntelliJ IDEA。
- 计算机已安装 DBManager 或者 xgconsole。
- 计算机已部署 XuguDB 12.0.0 或有能连接访问的虚谷数据库实例。
提示
本文档示例程序运行使用的软件为IntelliJ IDEA 2025.1.2 (Community Edition),也可以按照自己的喜好选择其它开发工具运行此示例程序。
2.2 操作步骤
提示
本文是在Windows环境中进行操作说明的,如果使用的是其它操作环境,那么与本文中的步骤可能存在不同。
- 导入
xugu-shardingsphere-demo
项目到 IDEA 中。 - 修改
xugu-shardingsphere-demo
项目中数据库连接信息。 - 运行
xugu-shardingsphere-demo
项目。
2.2.1 导入 xugu-shardingsphere-demo
项目到 IDEA 中
参考 IntelliJ IDEA 官网文档,导入项目。
- 启动 IntelliJ IDEA。 如果欢迎屏幕打开,请选择左侧栏目中项目(Projects)-> 右侧选项打开(Open)。 否则,请转到左上角主菜单的 文件(File)-> 打开(Open)。
- 在打开的对话框中,选择下载的源代码、库目录下的二级目录
xugu-shardingsphere4.1.1
,然后点击 Select Folder 打开。
项目结构设置
更改项目 SDK 设置:请点击右上角工具栏上的齿轮⚙设置按钮并选择项目结构按钮。 或者,前往 文件(File)-> 项目结构(Project Structure...) 或按
Ctrl
+Alt
+Shift
+S
。图 2.1 xugu-shardingsphere4.1.1项目JDK设置
项目 Maven 设置:文件 -> 设置 -> 构建、执行、部署 -> 构建工具 -> Maven。
图 2.2 xugu-shardingsphere4.1.1项目Maven设置
pom.xml 依赖设置
图 2.3 xugu-shardingsphere4.1.1依赖设置
仔细阅读
xugu-shardingsphere4.1.1/README.md
,在项目根目录中执行以下脚本,将兼容虚谷数据库的 sharding-jdbc 安装到本地 Maven 仓库,并刷新/重新加载 Maven 项目。
提示
若已执行步骤1.2 源码安装,则忽略此步骤执行。
shell
mvn install:install-file -Dfile=./lib/shardingsphere-common-4.1.1.jar -DgroupId=org.apache.shardingsphere -DartifactId=shardingsphere-common -Dversion=4.1.1 -Dpackaging=jar
mvn install:install-file -Dfile=./lib/shardingsphere-sql-parser-binder-4.1.1.jar -DgroupId=org.apache.shardingsphere -DartifactId=shardingsphere-sql-parser-binder -Dversion=4.1.1 -Dpackaging=jar
2.2.2 修改 xugu-shardingsphere-demo
项目中数据库连接信息
修改
xugu-shardingsphere4.1.1/src/main/resources/application.yml
中配置的多环境配置文件,选择cluster
。图 2.4 xugu-shardingsphere4.1.1选择运行环境
执行项目中
xugu-shardingsphere4.1.1/sql/cluster
目录中以下sql,创建数据库和表结构,对应后续步骤中分库分表配置。图 2.5 xugu-shardingsphere4.1.1数据库SQL文件
修改
xugu-shardingsphere4.1.1/src/main/resources/application-cluster.yml
文件中的数据库连接信息以及分片策略。- 示例代码如下:
yaml#数据分片 spring: shardingsphere: datasource: #数据源名称,多数据源以逗号分隔 names: ds0,ds1,ds2 ds0: #数据库驱动类名 driverClassName: com.xugu.cloudjdbc.Driver #数据库url连接, url: jdbc:xugu://127.0.0.1:5138/rdss0?compatiblemode=MYSQL #数据库用户名 username: SYSDBA #数据库密码 password: SYSDBA #数据库连接池类名称 type: com.alibaba.druid.pool.DruidDataSource #数据库连接池的其它属性 validationQuery: SELECT 1 FROM DUAL ds1: driverClassName: com.xugu.cloudjdbc.Driver url: jdbc:xugu://127.0.0.1:5138/rdss1?compatiblemode=MYSQL username: SYSDBA password: SYSDBA type: com.alibaba.druid.pool.DruidDataSource validationQuery: SELECT 1 FROM DUAL ds2: driverClassName: com.xugu.cloudjdbc.Driver url: jdbc:xugu://127.0.0.1:5138/rdss2?compatiblemode=MYSQL username: SYSDBA password: SYSDBA type: com.alibaba.druid.pool.DruidDataSource validationQuery: SELECT 1 FROM DUAL props: #是否开启SQL显示,默认值: false sql.show: true #工作线程数量,默认值: CPU核数 executor.size: 6 sharding: tables: #逻辑表名 orders: #由数据源名 + 表名组成,以小数点分隔。多个表以逗号分隔,支持inline表达式。 #缺省表示使用已知数据源与逻辑表名称生成数据节点,用于广播表(即每个库中都需要一个同样的表用于关联查询,多为字典表) #或只分库不分表且所有库的表结构完全一致的情况 actual-data-nodes: ds$->{0..1}.orders_$->{1..5} keyGenerator: #自增列名称,缺省表示不使用自增主键生成器 column: id #自增列值生成器类型,缺省表示使用默认自增列值生成器。可使用用户自定义的列值生成器或选择内置类型:SNOWFLAKE/UUID type: SNOWFLAKE #分库策略,缺省表示使用默认分库策略,以下的standard、complex、inline、hint分片策略只能选其一 database-strategy: #行表达式分片策略 inline: #分片列名称 shardingColumn: id #分片算法行表达式,需符合groovy语法 algorithmExpression: ds$->{id % 2} # #Hint分片策略 # hint: # #Hint分片算法类名称。该类需实现HintShardingAlgorithm接口并提供无参数的构造器 # algorithm-class-name: com.example.shardingjdbcdemo.demo1.config.OrdersDbHintAlgorithm #分表策略,同分库策略 table-strategy: inline: shardingColumn: id algorithmExpression: orders_$->{id % 5 + 1} # hint: # algorithm-class-name: com.example.shardingjdbcdemo.demo1.config.OrderTableHintAlgorithm order_item: actual-data-nodes: ds$->{0..1}.order_item_$->{1..5} database-strategy: inline: shardingColumn: order_id algorithmExpression: ds$->{order_id % 2} table-strategy: inline: shardingColumn: order_id algorithmExpression: order_item_$->{order_id % 5 + 1} user: actualDataNodes: ds2.user_$->{2024..2026} keyGenerator: column: id type: SNOWFLAKE tableStrategy: #用于单分片键的标准分片场景 standard: #分片列名称 shardingColumn: create_time #精确分片算法类名称,用于=和IN。该类需实现PreciseShardingAlgorithm接口并提供无参数的构造器 precise-algorithm-class-name: com.example.shardingjdbcdemo.demo1.config.UserTableStandardPreciseAlgorithm #范围分片算法类名称,用于BETWEEN,可选。该类需实现RangeShardingAlgorithm接口并提供无参数的构造器 rangeAlgorithmClassName: com.example.shardingjdbcdemo.demo1.config.UserTableRangeShardingAlgorithm #广播表规则列表 broadcast-tables: - dict #绑定表规则列表 binding-tables: - orders,order_item #数据脱敏 encryptRule: tables: #逻辑表名 user: columns: #逻辑字段名 pwd: #存储密文的字段 cipherColumn: pwd_cipher #加密器名字 encryptor: my_aes idCardNumber: cipherColumn: id_card_number_cipher encryptor: my_md5 encryptors: #自定义加密器名字 my_aes: #加解密器类型,可自定义或选择内置类型:MD5/AES type: aes #属性配置, 注意:使用AES加密器,需要配置AES加密器的KEY属性:aes.key.value props: aes.key.value: 123123pwd my_md5: type: md5
检查配置文件中引用的自定义分片算法是否存在。
图 2.6 xugu-shardingsphere4.1.1自定义分片算法
2.2.3 运行 xugu-shardingsphere-demo
项目。
测试绑定表分库分表
运行方法:
com.example.shardingjdbcdemo.ConnectSelectTest#testInsertOrderItem
,测试数据写入。图 2.7 xugu-shardingsphere4.1.1测试绑定表数据写入
运行方法:
com.example.shardingjdbcdemo.ConnectSelectTest#testConnectSelect
,测试数据读取。图 2.8 xugu-shardingsphere4.1.1测试绑定表数据读取
手动查询数据库中数据,验证分片规则。
- rdss0: 抽样查询表 orders_1 中 id 列是否都以0结尾(id % 5 + 1 = 1)&(id % 2 = 0)。
textSQL> use rdss0; Reconnect ok. Database switch to rdss0 Execute successful. Use time:92 ms. SQL> select * from ORDERS_1 limit 10; +-----+-----+------------+-------------+--------------+--------------+--------+ | ID | UID | ORDER_TYPE | CUSTOMER_ID | AMOUNT | LEVEL | Enable | +-----+-----+------------+-------------+--------------+--------------+--------+ | 260 | 21 | 260 | 260 | 2.600000e+05 | 2.600000e+05 | 1 | | 270 | 1 | 270 | 270 | 2.700000e+05 | 2.700000e+05 | 1 | | 280 | 11 | 280 | 280 | 2.800000e+05 | 2.800000e+05 | 1 | | 290 | 21 | 290 | 290 | 2.900000e+05 | 2.900000e+05 | 1 | | 300 | 1 | 300 | 300 | 3.000000e+05 | 3.000000e+05 | 1 | | 310 | 11 | 310 | 310 | 3.100000e+05 | 3.100000e+05 | 1 | | 320 | 21 | 320 | 320 | 3.200000e+05 | 3.200000e+05 | 1 | | 330 | 1 | 330 | 330 | 3.300000e+05 | 3.300000e+05 | 1 | | 340 | 11 | 340 | 340 | 3.400000e+05 | 3.400000e+05 | 1 | | 350 | 21 | 350 | 350 | 3.500000e+05 | 3.500000e+05 | 1 | +-----+-----+------------+-------------+--------------+--------------+--------+ (10 rows) Use time:1 ms. SQL>
- rdss0: 抽样查询表 order_item_1 中 order_id 列是否都等于 orders_1 中 id。
textSQL> select * from ORDER_ITEM_1 limit 10; +-----+----------+------------------+-------+ | ID | ORDER_ID | ADDRESS | PRICE | +-----+----------+------------------+-------+ | 261 | 260 | 天府大道1街260号 | 271 | | 262 | 260 | 天府大道2街260号 | 272 | | 271 | 270 | 天府大道1街270号 | 281 | | 272 | 270 | 天府大道2街270号 | 282 | | 281 | 280 | 天府大道1街280号 | 291 | | 282 | 280 | 天府大道2街280号 | 292 | | 291 | 290 | 天府大道1街290号 | 301 | | 292 | 290 | 天府大道2街290号 | 302 | | 301 | 300 | 天府大道1街300号 | 311 | | 302 | 300 | 天府大道2街300号 | 312 | +-----+----------+------------------+-------+ (10 rows) Use time:0 ms. SQL>
- rdss0: 抽样查询表 ORDERS_3 中 id 列是否都以2结尾(id % 5 + 1 = 3)&(id % 2 = 0)。
textSQL> select * from ORDERS_3 limit 10; +-----+-----+------------+-------------+--------------+--------------+--------+ | ID | UID | ORDER_TYPE | CUSTOMER_ID | AMOUNT | LEVEL | Enable | +-----+-----+------------+-------------+--------------+--------------+--------+ | 252 | 13 | 252 | 252 | 2.520000e+05 | 2.520000e+05 | 1 | | 262 | 23 | 262 | 262 | 2.620000e+05 | 2.620000e+05 | 1 | | 272 | 3 | 272 | 272 | 2.720000e+05 | 2.720000e+05 | 1 | | 282 | 13 | 282 | 282 | 2.820000e+05 | 2.820000e+05 | 1 | | 292 | 23 | 292 | 292 | 2.920000e+05 | 2.920000e+05 | 1 | | 302 | 3 | 302 | 302 | 3.020000e+05 | 3.020000e+05 | 1 | | 312 | 13 | 312 | 312 | 3.120000e+05 | 3.120000e+05 | 1 | | 322 | 23 | 322 | 322 | 3.220000e+05 | 3.220000e+05 | 1 | | 332 | 3 | 332 | 332 | 3.320000e+05 | 3.320000e+05 | 1 | | 342 | 13 | 342 | 342 | 3.420000e+05 | 3.420000e+05 | 1 | +-----+-----+------------+-------------+--------------+--------------+--------+ (10 rows) Use time:0 ms. SQL>
- rdss0: 抽样查询表 order_item_3 中 order_id 列是否都等于 orders_3 中 id。
textSQL> select * from ORDER_ITEM_3 limit 10; +-----+----------+------------------+-------+ | ID | ORDER_ID | ADDRESS | PRICE | +-----+----------+------------------+-------+ | 253 | 252 | 天府大道1街252号 | 263 | | 254 | 252 | 天府大道2街252号 | 264 | | 263 | 262 | 天府大道1街262号 | 273 | | 264 | 262 | 天府大道2街262号 | 274 | | 273 | 272 | 天府大道1街272号 | 283 | | 274 | 272 | 天府大道2街272号 | 284 | | 283 | 282 | 天府大道1街282号 | 293 | | 284 | 282 | 天府大道2街282号 | 294 | | 293 | 292 | 天府大道1街292号 | 303 | | 294 | 292 | 天府大道2街292号 | 304 | +-----+----------+------------------+-------+ (10 rows) Use time:0 ms. SQL>
- rdss1:抽样查询表 ORDERS_1 中 id 列是否都以5结尾(id % 5 + 1 = 1)&(id % 2 = 1)。
textSQL> use rdss1; Database switch to rdss1 Execute successful. Use time:2 ms. SQL> select * from ORDERS_1 limit 10; +-----+-----+------------+-------------+--------------+--------------+--------+ | ID | UID | ORDER_TYPE | CUSTOMER_ID | AMOUNT | LEVEL | Enable | +-----+-----+------------+-------------+--------------+--------------+--------+ | 255 | 16 | 255 | 255 | 2.550000e+05 | 2.550000e+05 | 1 | | 265 | 26 | 265 | 265 | 2.650000e+05 | 2.650000e+05 | 1 | | 275 | 6 | 275 | 275 | 2.750000e+05 | 2.750000e+05 | 1 | | 285 | 16 | 285 | 285 | 2.850000e+05 | 2.850000e+05 | 1 | | 295 | 26 | 295 | 295 | 2.950000e+05 | 2.950000e+05 | 1 | | 305 | 6 | 305 | 305 | 3.050000e+05 | 3.050000e+05 | 1 | | 315 | 16 | 315 | 315 | 3.150000e+05 | 3.150000e+05 | 1 | | 325 | 26 | 325 | 325 | 3.250000e+05 | 3.250000e+05 | 1 | | 335 | 6 | 335 | 335 | 3.350000e+05 | 3.350000e+05 | 1 | | 345 | 16 | 345 | 345 | 3.450000e+05 | 3.450000e+05 | 1 | +-----+-----+------------+-------------+--------------+--------------+--------+ (10 rows) Use time:0 ms. SQL>
- rdss1: 抽样查询表 order_item_1 中 order_id 列是否都等于 orders_1 中 id。
textSQL> select * from ORDER_ITEM_1 limit 10; +-----+----------+------------------+-------+ | ID | ORDER_ID | ADDRESS | PRICE | +-----+----------+------------------+-------+ | 256 | 255 | 天府大道1街255号 | 266 | | 257 | 255 | 天府大道2街255号 | 267 | | 266 | 265 | 天府大道1街265号 | 276 | | 267 | 265 | 天府大道2街265号 | 277 | | 276 | 275 | 天府大道1街275号 | 286 | | 277 | 275 | 天府大道2街275号 | 287 | | 286 | 285 | 天府大道1街285号 | 296 | | 287 | 285 | 天府大道2街285号 | 297 | | 296 | 295 | 天府大道1街295号 | 306 | | 297 | 295 | 天府大道2街295号 | 307 | +-----+----------+------------------+-------+ (10 rows) Use time:1 ms. SQL>
- rdss1:抽样查询表 ORDERS_3 中 id 列是否都以7结尾(id % 5 + 1 = 3)&(id % 2 = 1)。
textSQL> select * from ORDERS_3 limit 10; +-----+-----+------------+-------------+--------------+--------------+--------+ | ID | UID | ORDER_TYPE | CUSTOMER_ID | AMOUNT | LEVEL | Enable | +-----+-----+------------+-------------+--------------+--------------+--------+ | 257 | 18 | 257 | 257 | 2.570000e+05 | 2.570000e+05 | 1 | | 267 | 28 | 267 | 267 | 2.670000e+05 | 2.670000e+05 | 1 | | 277 | 8 | 277 | 277 | 2.770000e+05 | 2.770000e+05 | 1 | | 287 | 18 | 287 | 287 | 2.870000e+05 | 2.870000e+05 | 1 | | 297 | 28 | 297 | 297 | 2.970000e+05 | 2.970000e+05 | 1 | | 307 | 8 | 307 | 307 | 3.070000e+05 | 3.070000e+05 | 1 | | 317 | 18 | 317 | 317 | 3.170000e+05 | 3.170000e+05 | 1 | | 327 | 28 | 327 | 327 | 3.270000e+05 | 3.270000e+05 | 1 | | 337 | 8 | 337 | 337 | 3.370000e+05 | 3.370000e+05 | 1 | | 347 | 18 | 347 | 347 | 3.470000e+05 | 3.470000e+05 | 1 | +-----+-----+------------+-------------+--------------+--------------+--------+ (10 rows) Use time:1 ms. SQL>
- rdss1: 抽样查询表 order_item_3 中 order_id 列是否都等于 orders_3 中 id。
textSQL> select * from ORDER_ITEM_3 limit 10; +-----+----------+------------------+-------+ | ID | ORDER_ID | ADDRESS | PRICE | +-----+----------+------------------+-------+ | 258 | 257 | 天府大道1街257号 | 268 | | 259 | 257 | 天府大道2街257号 | 269 | | 268 | 267 | 天府大道1街267号 | 278 | | 269 | 267 | 天府大道2街267号 | 279 | | 278 | 277 | 天府大道1街277号 | 288 | | 279 | 277 | 天府大道2街277号 | 289 | | 288 | 287 | 天府大道1街287号 | 298 | | 289 | 287 | 天府大道2街287号 | 299 | | 298 | 297 | 天府大道1街297号 | 308 | | 299 | 297 | 天府大道2街297号 | 309 | +-----+----------+------------------+-------+ (10 rows) Use time:0 ms. SQL>
测试清空数据库中数据
- 测试前清空数据

三、常见问题&解决办法
- SQL 使用聚合函数如 COUNT( * ) 不加别名并且加 WHERE 条件时报错:
Can't find index: AggregationProjection(type=COUNT, innerExpression=( * ), alias=Optional.empty, derivedAggregationProjections=[], index=-1), please add alias for aggregate selections
- 数据源配置(
spring.shardingsphere.datasource.ds0.url
)中配置连接属性 compatiblemode=MYSQL - 仅支持特定常见的聚合函数使用,详情见官网使用规范-SQL。
- 数据源配置(
- ShardingSphere 在升级到 5.x 版本时,对数据库表名大小写敏感,而虚谷数据库创建表名默认为大写,此时分片规则配置小写表名会报错:
Caused by:java.sql.SQLException:[E19132]语法错误
[E19260 L1 C7]期待符号:syntax error, unexpected FROM
- 方案一:如果必须需要小写表名,创建数据库表结构的 SQL 语句时,对表名小写并且加反引号``或者双引号""包裹。
- 示例代码
sql-- 注意:开启 compatiblemode=MYSQL 兼容模式时,使用双引号可能会报语法错误 create table `orders_0`(`id` BIGINT,`uid` BIGINT,`order_type` INTEGER,`customer_id` int,`amount` DOUBLE ,`level` DOUBLE,`enable` int); create table "orders_0"(`id` BIGINT,`uid` BIGINT,`order_type` INTEGER,`customer_id` int,`amount` DOUBLE ,`level` DOUBLE,`enable` int);
- 方案二:如果无法更改数据库中表信息,则通过修改分片规则
sharding-cluster.yml
中表名为大写来解决。- 示例代码
yamlrules: - !SHARDING tables: orders: # 大写表名ORDERS actualDataNodes: ds$->{0..1}.ORDERS_$->{0..4} keyGenerateStrategy: column: id keyGeneratorName: snowflake-method databaseStrategy: standard: shardingColumn: id shardingAlgorithmName: orders-database-inline tableStrategy: standard: shardingColumn: id shardingAlgorithmName: orders-table-inline shardingAlgorithms: orders-database-inline: type: INLINE props: algorithm-expression: ds$->{id % 2} allow-range-query-with-inline-sharding: true orders-table-inline: type: INLINE props: algorithm-expression: ORDERS_$->{id % 5} allow-range-query-with-inline-sharding: true
- 方案一:如果必须需要小写表名,创建数据库表结构的 SQL 语句时,对表名小写并且加反引号``或者双引号""包裹。
- 数据源级别的异构数据库
- 不想使用 ShardingSphere 自动创建数据源,而是使用自定义数据源 Bean:
shardingDataSource
- 方案一:
pom.xml
不使用sharding-jdbc-spring-boot-starter
依赖项,改用sharding-jdbc-core
。- 示例代码
xml<dependency> <groupId>org.apache.shardingsphere</groupId> <artifactId>sharding-jdbc-core</artifactId> <version>4.1.1</version> </dependency>
- 方案二:主启动类
@SpringBootApplication
中排除数据源自动装配- 示例代码
javapackage com.example.shardingjdbcdemo; import org.apache.shardingsphere.shardingjdbc.spring.boot.SpringBootConfiguration; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.transaction.annotation.EnableTransactionManagement; @SpringBootApplication(exclude = {SpringBootConfiguration.class}) @EnableTransactionManagement public class ShardingjdbcDemoApplication { public static void main(String[] args) { SpringApplication.run(ShardingjdbcDemoApplication.class, args); } }
- 方案一:
- 其它常见问题见官网FAQ