一、Sharding-JDBC简介

Sharding-JDBC是ShardingSphere的第一个产品,也是ShardingSphere的前身。 它定位为轻量级Java框架,在Java的JDBC层提供的额外服务。它使用客户端直连数据库,以jar包形式提供服务,无需额外部署和依赖,可理解为增强版的JDBC驱动,完全兼容JDBC和各种ORM框架。

  • 适用于任何基于JDBC的ORM框架,如:JPA, Hibernate, Mybatis, Spring JDBC Template或直接使用JDBC。
  • 支持任何第三方的数据库连接池,如:DBCP, C3P0, BoneCP, Druid, HikariCP等。
  • 支持任意实现JDBC规范的数据库。目前支持MySQL,Oracle,SQLServer,PostgreSQL以及任何遵循SQL92标准的数据库。

使用Sharding-JDBC可以实现数据分片、读写分离、分布式事务等需求。

本篇文章主要介绍通过Sharding-JDBC实现数据分片,即分库分表。

Sharding-JDBC提供了4种配置方式,用于不同的使用场景。本文只介绍Spring命名空间配置和SpringBoot配置。

二、准备工作

在虚拟机上部署两台Mysql服务器,IP地址分别为192.168.0.150,192.168.0.152。

然后创建数据库,数据库名分别为sharding_order,shard_order以示区分。

在sharding_order,shard_order中均创建两张结构一致的表,表名分别为t_order_1,t_order_2。建表语句如下:

CREATE TABLE `t_order_1` (  `id` int NOT NULL,  `order_amount` decimal(10,2) NOT NULL,  `order_status` int NOT NULL,  `user_id` int NOT NULL,  PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

三、创建项目

在IDEA中新建SpringBoot项目,选择以下依赖

然后通过MyBatis Generator创建实体类和Dao层接口及Mapper文件。配置如下:

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE generatorConfiguration        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"><generatorConfiguration>    <!-- 配置文件路径 -->    <properties resource="dbconfig.properties"/>    <!--数据库驱动包路径 已经在Maven的pom配置过了,这里就不需要了-->    <!--<classPathEntry location="${drive.class.path}"/>-->    <context id="MySQLTables" targetRuntime="MyBatis3Simple">        <!--关闭注释 -->        <commentGenerator>            <property name="suppressDate" value="true"/>            <!-- 是否去除自动生成的注释 true:是 : false:否 -->            <property name="suppressAllComments" value="true"/>        </commentGenerator>        <!--数据库连接信息 -->        <jdbcConnection driverClass="${jdbc.driver}" connectionURL="${jdbc.url}" userId="${jdbc.username}"                        password="${jdbc.password}">        </jdbcConnection>        <!--        默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer            true,把JDBC DECIMAL 和 NUMERIC 类型解析为java.math.BigDecimal         -->        <javaTypeResolver>            <property name="forceBigDecimals" value="false"/>        </javaTypeResolver>        <!--生成的model 包路径 -->        <javaModelGenerator targetPackage="${model.package}" targetProject="src\main\java">            <property name="enableSubPackages" value="true"/>            <property name="trimStrings" value="true"/>        </javaModelGenerator>        <!--生成xml mapper文件 路径 -->        <sqlMapGenerator targetPackage="${xml.mapper.package}" targetProject="src\main\resources">            <property name="enableSubPackages" value="true"/>        </sqlMapGenerator>        <!-- 生成的Dao接口 的包路径 -->        <javaClientGenerator type="XMLMAPPER" targetPackage="${dao.package}" targetProject="src\main\java">            <property name="enableSubPackages" value="true"/>        </javaClientGenerator>        <!--对应数据库表名 -->        <table schema="sharding_order" tableName="t_order_1" domainObjectName="Order"></table>    </context></generatorConfiguration>

项目创建完成后的结构如下:

四、Spring命名空间配置

在pom文件中引入Sharding-JDBC命名空间配置的依赖

<dependency>    <groupId>org.apache.shardingsphere</groupId>    <artifactId>sharding-jdbc-spring-namespace</artifactId>    <version>4.1.1</version></dependency>

在resources目录下新建配置文件sharding-jdbc.xml,内容如下:

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"       xmlns:p="http://www.springframework.org/schema/p"       xmlns:context="http://www.springframework.org/schema/context"       xmlns:tx="http://www.springframework.org/schema/tx"       xmlns:sharding="http://shardingsphere.apache.org/schema/shardingsphere/sharding"       xsi:schemaLocation="http://www.springframework.org/schema/beans                        http://www.springframework.org/schema/beans/spring-beans.xsd                        http://shardingsphere.apache.org/schema/shardingsphere/sharding                        http://shardingsphere.apache.org/schema/shardingsphere/sharding/sharding.xsd                        http://www.springframework.org/schema/context                        http://www.springframework.org/schema/context/spring-context.xsd                        http://www.springframework.org/schema/tx                        http://www.springframework.org/schema/tx/spring-tx.xsd http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring.xsd">        <!-- 配置数据源,对应分片的数据库,有几个数据库就需要配置几个数据源 -->    <!-- 这里数据源使用的是HikariDataSource,也可以使用其他的数据源 -->    <bean id="ds0" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>        <property name="jdbcUrl" value="jdbc:mysql://192.168.0.150:3306/sharding_order?serverTimezone=Asia/Shanghai&amp;useSSL=false"/>        <property name="username" value="root"/>        <property name="password" value=""/>    </bean>    <bean id="ds1" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>        <property name="jdbcUrl" value="jdbc:mysql://192.168.0.152:3306/shard_order?serverTimezone=Asia/Shanghai&amp;useSSL=false"/>        <property name="username" value="root"/>        <property name="password" value=""/>    </bean>        <!-- 配置sharding-jdbc的数据源 -->    <sharding:data-source id="shardingDataSource">        <!--data-source-names数据源Bean列表,多个Bean以逗号分隔-->        <sharding:sharding-rule data-source-names="ds0,ds1">            <!--table-rules表分片规则配置对象-->            <sharding:table-rules>                <!--logic-table逻辑表名称-->                <!--actual-data-nodes由数据源名 + 表名组成,以小数点分隔。多个表以逗号分隔,支持inline表达式。-->                <sharding:table-rule logic-table="t_order" actual-data-nodes="ds$->{0..1}.t_order_$->{1..2}" database-strategy-ref="databaseShardingStrategy" table-strategy-ref="tableShardingStrategy" />            </sharding:table-rules>        </sharding:sharding-rule>    </sharding:data-source>    <!--数据库分片策略,使用user_id作为分片的列,user_id对2取模,user_id为奇数的分到ds1,偶数的则分到ds0-->    <sharding:inline-strategy id="databaseShardingStrategy" sharding-column="user_id" algorithm-expression="ds$->{user_id % 2}"/>    <!--表分片策略,使用id作为分片的列,id对2取模然后加1,id为奇数的分到t_order_2,偶数的则分到t_order_1-->    <sharding:inline-strategy id="tableShardingStrategy" sharding-column="id" algorithm-expression="t_order_$->{id % 2 + 1}"/>    <!--配置Mybatis的SqlSessionFactoryBean-->    <bean class="org.mybatis.spring.SqlSessionFactoryBean">        <property name="dataSource" ref="shardingDataSource"/>        <property name="mapperLocations" value="classpath*:/mapper/*.xml"/>    </bean></beans>

在启动类上添加@ImportResource@MapperScan注释

在测试类中创建测试方法

@SpringBootTestclass ShardingDemoApplicationTests {    @Resource    OrderMapper orderMapper;    @Test    void contextLoads() {    }    @Test    public void testOrder(){        Order order=new Order();        order.setId(21);        order.setOrderAmount(BigDecimal.TEN);        order.setOrderStatus(0);        order.setUserId(1);        orderMapper.insert(order);    }}

这里id设置为21,user_id设置为1,根据前面配置的分库规则使用user_id取模结果为1,所以该记录会落在数据源ds1中,即152服务器上的数据库。根据分表的规则id取模再加1,结果为2,所以该记录最终落在152数据库shard_order数据库中的t_order_2表中。

再将id设置为22,user_id设置为2,该记录最终应落在150数据库sharding-order的t_order_1中。

五、SpringBoot配置

将Spring命名空间配置的依赖删除或注释,引入SpringBoot配置的依赖

<dependency>     <groupId>org.apache.shardingsphere</groupId>     <artifactId>sharding-jdbc-spring-boot-starter</artifactId>     <version>4.1.1</version></dependency>-->

在application.properties中添加以下配置

spring.shardingsphere.datasource.names=ds0,ds1spring.shardingsphere.datasource.ds0.type=com.zaxxer.hikari.HikariDataSourcespring.shardingsphere.datasource.ds0.driver-class-name=com.mysql.cj.jdbc.Driverspring.shardingsphere.datasource.ds0.jdbcUrl=jdbc:mysql://192.168.0.150:3306/sharding_orderspring.shardingsphere.datasource.ds0.username=rootspring.shardingsphere.datasource.ds0.password=spring.shardingsphere.datasource.ds1.type=com.zaxxer.hikari.HikariDataSourcespring.shardingsphere.datasource.ds1.driver-class-name=com.mysql.cj.jdbc.Driverspring.shardingsphere.datasource.ds1.jdbcUrl=jdbc:mysql://192.168.0.152:3306/shard_orderspring.shardingsphere.datasource.ds1.username=rootspring.shardingsphere.datasource.ds1.password=spring.shardingsphere.sharding.tables.t_order.actual-data-nodes=ds$->{0..1}.t_order_$->{1..2}spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.sharding-column=idspring.shardingsphere.sharding.tables.t_order.table-strategy.inline.algorithm-expression=t_order_$->{id % 2 + 1}spring.shardingsphere.sharding.tables.t_order.database-strategy.inline.sharding-column=user_idspring.shardingsphere.sharding.tables.t_order.database-strategy.inline.algorithm-expression=ds$->{user_id % 2}mybatis.mapper-locations=/mapper/*.xml

将启动类上的@ImportResource删除或者注释

测试方法同Spring命名空间配置的方式。