ShardingSphereJDBC分库分表Demo【附源码】

数据库相关知识脉络图

目录

数据库相关知识脉络图

ShardingSphere简介

什么情况下考虑分库分表呢?

ShardingSphere JDBC基本概念解释

ShardingSphere JDBC使用

demo地址github

经典三步:

demo介绍:

单库分表

分库分表-inline模式-普通不支持范围查询

 分库分表-standard模式-范围查询

 分库分表-complex模式-混合字段范围查询

 分库分表-hint模式-指定数据库/表


ShardingSphere简介

官网地址

ShardingSphere是一套开源的分布式数据库解决方案组成的生态圈,包含:

  • ShardingSphere JDBC
    • 核心功能:分库分表 & 读写分离
    • 引入进我们程序中,提供api去操作分库分表的jar包。
    • 任意jdbc型数据库都可以使用。
    • 侵入性强,也灵活。
  • ShardingSphere Proxy
    • 隔离在我们程序之外的应用,提供操作分库分表功能。
    • 仅供MySQL,PostgreSQL使用。
    • 独立部署,需提前定义好与数据库交互的逻辑。
  • Sidecar(规划中)

什么情况下考虑分库分表呢?

  • 单表数据未来三年超过500万数据
  • 单表数据大小未来三年超过2G
  • 根据实际业务

ShardingSphere JDBC基本概念解释

序号名词解释
1逻辑表把一类相同的表、相同增删改查逻辑的表,抽象成一个“逻辑表”,不真实存在。
2真实表真实存在的表
3广播表所有库里这个表的逻辑字段使用逻辑都相同的表,例如数据字典表要统一。
4绑定表像是主表和子表的关系,不可分割,尽量保持一致的表。
5分片键例如插入数据时候,根据哪个字段来路由数据进入到各个库表?那个字段就是分片键
6分片算法根据什么算法去路由?取摩运算?直接指定库名?
7分片策略= 分片键 + 分片算法

ShardingSphere JDBC使用

demo地址github

https://github.com/lxnxxwl/shardingspheredemo.git

经典三步:

1、 建表:例如mall_order_1 \ mall_order_2..这样尾数有关联易表达的。

2、 引入sharding sphere jdbc的依赖

3、 编写配置文件

demo介绍:

  1. maven聚合项目:common包中实体类,其他包为不同配置的分库分表demo依赖common。
  2. 使用mybatis plus 进行操作数据库(测试用例简单)。mapper在各个demo包中。
  3. 测试例子在各个demo的test包中。
  4. 配置文件采用.properties文件配置。

单库分表

  • 首先要自己建表(真实表):
    • 这里就是在一个数据库里建两张相同的表mall_order_1 \ mall_order_2。
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for mall_order_1
-- ----------------------------
DROP TABLE IF EXISTS `mall_order_1`;
CREATE TABLE `mall_order_1` (
  `id` bigint NOT NULL,
  `order_name` varchar(32) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

SET FOREIGN_KEY_CHECKS = 1;
  • 引入pom依赖。
    • springboot为例
        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
            <version>4.1.1</version>
        </dependency>

​​​​​​

  • 编写配置文件【单库分表】
#sharding jdbc 数据库 起名 m1
spring.shardingsphere.datasource.names=m1
spring.shardingsphere.datasource.m1.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.m1.url=jdbc:mysql://localhost:3306/test?characterEncoding=utf-8&serverTimezone=UTC&useSSL=false
spring.shardingsphere.datasource.m1.username=root
spring.shardingsphere.datasource.m1.password=root

# 1.哪些节点?==哪几张表
spring.shardingsphere.sharding.tables.mall_order.actual-data-nodes=m1.mall_order_$->{1..2}
# 2.主键是哪一列?
spring.shardingsphere.sharding.tables.mall_order.key-generator.column=cid
# 3.主键生成策略是什么? 可自定义,此处采用已集成的雪花算法
spring.shardingsphere.sharding.tables.mall_order.key-generator.type=SNOWFLAKE
spring.shardingsphere.sharding.tables.mall_order.key-generator.props.worker.id=1
# 4.分片键:inline模式下按id分表
spring.shardingsphere.sharding.tables.mall_order.table-strategy.inline.sharding-column=cid
# 5.分片算法:ID取摩
spring.shardingsphere.sharding.tables.mall_order.table-strategy.inline.algorithm-expression=mall_order_$->{cid%2+1}

spring.shardingsphere.props.sql.show = true
spring.main.allow-bean-definition-overriding=true
  • mapper:     
public interface MallOrderMapper extends BaseMapper<MallOrder> {
}
  • 测试类
@RunWith(SpringRunner.class)
@SpringBootTest
public class OnedbApplicationTests {

    @Resource
    private MallOrderMapper orderMapper;

    @Test
    public void addOrder(){
        for(int i = 0 ; i < 10 ; i ++){
            MallOrder order = new MallOrder();
            order.setOrderName("第"+i+"个订单");
            orderMapper.insert(order);
        }
    }

}

 

分库分表-inline模式-普通不支持范围查询

  • 首先要自己建表(真实表):
    • 这里就是在test数据库里建两张相同的表mall_order_1 \ mall_order_2。在test2中建两张相同的表mall_order_1 \ mall_order_2 。建表语句同上。
  • 依赖同上:放在父工程pom里即可
  • 配置文件:
# 应用名称
spring.application.name=twodb
#配置数据库别名:两个数据库
spring.shardingsphere.datasource.names=db1,db2
#第一个数据库 库名:test
spring.shardingsphere.datasource.db1.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.db1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.db1.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
spring.shardingsphere.datasource.db1.username=root
spring.shardingsphere.datasource.db1.password=root
#第二个数据库 库名:test2
spring.shardingsphere.datasource.db2.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.db2.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.db2.url=jdbc:mysql://localhost:3306/test2?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
spring.shardingsphere.datasource.db2.username=root
spring.shardingsphere.datasource.db2.password=root
#真实表有哪些
spring.shardingsphere.sharding.tables.mall_order.actual-data-nodes=db$->{1..2}.mall_order_$->{1..2}
#使用雪花算法自动生成id/主键生成策略
spring.shardingsphere.sharding.tables.mall_order.key-generator.column=id
spring.shardingsphere.sharding.tables.mall_order.key-generator.type=SNOWFLAKE
#spring.shardingsphere.sharding.tables.mall_order.key-generator.props.worker.id=1
#分片(分表:table-strategy)策略
#分片键ID
spring.shardingsphere.sharding.tables.mall_order.table-strategy.inline.sharding-column=id
#分片算法:根据ID是奇数->mall_order_1;是偶数->mall_order_2
spring.shardingsphere.sharding.tables.mall_order.table-strategy.inline.algorithm-expression=mall_order_$->{id%2+1}
#分片(分库:database-strategy)策略
#分片键ID
spring.shardingsphere.sharding.tables.mall_order.database-strategy.inline.sharding-column=id
#分片算法:根据ID是奇数->db1 = test;是偶数->db2 = test2
spring.shardingsphere.sharding.tables.mall_order.database-strategy.inline.algorithm-expression=db$->{id%2+1}
#显示sql语句
spring.shardingsphere.props.sql.show = true
spring.main.allow-bean-definition-overriding=true

  • mapper同上
  • 测试用例
@SpringBootTest
@RunWith(SpringRunner.class)
public class TwodbApplicationTests {
    @Resource
    private MallOrderMapper orderMapper;

    /**
     * 向两个数据库四张表插入数据
     */
    @Test
    public void addOrderToDB() {
        for(int i = 0 ; i < 10 ; i ++){
            MallOrder order = new MallOrder();
            order.setOrderName("分库后的第"+i+"个订单");
            orderMapper.insert(order);
        }
    }

    /**
     * 按id查找某条数据
     * Logic  SQL: SELECT  id,order_name  FROM mall_order WHERE (id = ?)
     * Actual SQL: db2 ::: SELECT  id,order_name  FROM mall_order_2
     * shardingsphere已经按策略优化查询sql,仅在id可能存在的test2库的mall_order_2这张表中进行一次查询
     */
    @Test
    public void queryDataById(){
        QueryWrapper<MallOrder> wrapper = new QueryWrapper<>();
        wrapper.eq("id",1415550634731560961L);
        MallOrder mallOrder = orderMapper.selectOne(wrapper);
        System.out.println(mallOrder);
    }

    /**
     * 范围查询:ID在xxx~zzz之间的所有数据查询
     * Inline strategy cannot support this type sharding:RangeRouteValue
     * 使用inline模式是不支持范围查询的
     */
    @Test
    public void queryDataByRang(){
        QueryWrapper<MallOrder> wrapper = new QueryWrapper<>();
        wrapper.between("id",1415550634731560961L,1415550634748338178L);
        List<MallOrder> mallOrders = orderMapper.selectList(wrapper);
        mallOrders.forEach(mallOrder -> System.out.println(mallOrder));
    }

    /**
     * 按id排序查询出所有数据
     * Logic  SQL: SELECT  id,order_name  FROM mall_order
     * Actual SQL: db1 ::: SELECT  id,order_name  FROM mall_order_1
     * Actual SQL: db1 ::: SELECT  id,order_name  FROM mall_order_2
     * Actual SQL: db2 ::: SELECT  id,order_name  FROM mall_order_1
     * Actual SQL: db2 ::: SELECT  id,order_name  FROM mall_order_2
     * 两个库的四张表全部查询一遍(有待优化)
     */
    @Test
    public void queryDataBySort(){
        QueryWrapper<MallOrder> wrapper = new QueryWrapper<>();
        wrapper.orderByDesc("id");
        List<MallOrder> mallOrders = orderMapper.selectList(wrapper);
        mallOrders.forEach(mallOrder -> System.out.println(mallOrder));
    }

}

注:inline模式不支持范围查询,使用standard自定义规则后实现范围查询

 分库分表-standard模式-范围查询

  • 相同的sql和依赖和mapper省略
  • 配置文件
# 应用名称
spring.application.name=twodb-standard
#配置数据库别名:两个数据库
spring.shardingsphere.datasource.names=db1,db2
#第一个数据库 库名:test
spring.shardingsphere.datasource.db1.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.db1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.db1.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
spring.shardingsphere.datasource.db1.username=root
spring.shardingsphere.datasource.db1.password=root
#第二个数据库 库名:test2
spring.shardingsphere.datasource.db2.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.db2.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.db2.url=jdbc:mysql://localhost:3306/test2?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
spring.shardingsphere.datasource.db2.username=root
spring.shardingsphere.datasource.db2.password=root
#真实表有哪些
spring.shardingsphere.sharding.tables.mall_order.actual-data-nodes=db$->{1..2}.mall_order_$->{1..2}
#使用雪花算法自动生成id/主键生成策略
spring.shardingsphere.sharding.tables.mall_order.key-generator.column=id
spring.shardingsphere.sharding.tables.mall_order.key-generator.type=SNOWFLAKE
#spring.shardingsphere.sharding.tables.mall_order.key-generator.props.worker.id=1


#分片(分表:table-strategy)策略
#分片键ID
spring.shardingsphere.sharding.tables.mall_order.table-strategy.standard.sharding-column=id
#分表算法(需自己实现):
spring.shardingsphere.sharding.tables.mall_order.table-strategy.standard.precise-algorithm-class-name=com.lixiunan.twodbstandard.algorithm.MyTablePreciseAlgorithm
#表范围查询算法(需自己实现):
spring.shardingsphere.sharding.tables.mall_order.table-strategy.standard.range-algorithm-class-name=com.lixiunan.twodbstandard.algorithm.MyTableRangeAlgorithm


#分片(分库:database-strategy)策略
#分片键ID
spring.shardingsphere.sharding.tables.mall_order.database-strategy.standard.sharding-column=id
#分库算法(需自己实现):
spring.shardingsphere.sharding.tables.mall_order.database-strategy.standard.precise-algorithm-class-name=com.lixiunan.twodbstandard.algorithm.MyDBPreciseAlgorithm
#库范围查找算法(需自己实现):
spring.shardingsphere.sharding.tables.mall_order.database-strategy.standard.range-algorithm-class-name=com.lixiunan.twodbstandard.algorithm.MyDBRangeAlgorithm
#显示sql语句
spring.shardingsphere.props.sql.show = true
spring.main.allow-bean-definition-overriding=true


  •  自己写实现类:自己实现分库分表的规则,自己实现范围查询的方法等等
  • 自己实现分库策略
/**
 * @Description : TODO 自己实现分库策略
 * @Author : lixiunan
 * @Date : 2021/7/15
 **/
public class MyDBPreciseAlgorithm implements PreciseShardingAlgorithm<Long> {
    @Override
    public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Long> shardingValue) {
        //把雪花算法生成的id取出
        Long id = shardingValue.getValue();
        //对id取摩得到的数字
        BigInteger key =
                BigInteger.valueOf(id).mod(new BigInteger("2")).add(new BigInteger("1"));
        //生成真实表的表名
        String dbName = "db" + key;
        if(availableTargetNames.contains(dbName)){
            return dbName;
        }
        throw new UnsupportedOperationException("找不到数据库");
    }
}
  • 自己实现分表策略
/**
 * @Description :
 * TODO 自己定制insert时按照什么算法去分发到不同表中:分片键的类型Lone传入泛型,确保此算法在范围查找时使用是有效的
 * @Author : lixiunan
 * @Date : 2021/7/15
 **/
public class MyTablePreciseAlgorithm implements PreciseShardingAlgorithm<Long> {
    @Override
    public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Long> shardingValue) {
        //把雪花算法生成的id取出
        Long id = shardingValue.getValue();
        //对id取摩得到表名的数字
        BigInteger key =
                BigInteger.valueOf(id).mod(new BigInteger("2")).add(new BigInteger("1"));
        //生成真实表的表名
        String tableName = shardingValue.getLogicTableName() + "_" + key;
        if(availableTargetNames.contains(tableName)){
            return tableName;
        }else {
            throw new UnsupportedOperationException("找不到表名");
        }
    }
}
  • 自己实现范围查找(库 + 表)
/**
 * @Description : TODO 分为查找时分库策略定制
 * @Author : lixiunan
 * @Date : 2021/7/15
 **/
public class MyDBRangeAlgorithm implements RangeShardingAlgorithm<Long> {
    @Override
    public Collection<String> doSharding(
            Collection<String> availableTargetNames, RangeShardingValue<Long> shardingValue) {
        //范围查询库
        return Arrays.asList("db1","db2");
    }
}
/**
 * @Description : TODO 定制范围查找时分表查找策略
 * @Author : lixiunan
 * @Date : 2021/7/15
 **/
public class MyTableRangeAlgorithm implements RangeShardingAlgorithm<Long> {
    @Override
    public Collection<String> doSharding(
            Collection<String> availableTargetNames, RangeShardingValue<Long> shardingValue) {
        String logicTableName = shardingValue.getLogicTableName();
        //范围查询表
        return Arrays.asList(logicTableName+"_1",logicTableName+"_2");
    }
}
  •  测试用例
@SpringBootTest
@RunWith(SpringRunner.class)
public class TwodbStandardApplicationTests {

    @Resource
    private MallOrderMapper orderMapper;
    /**
     * 向两个数据库四张表插入数据
     */
    @Test
    public void addOrderToDB() {
        for(int i = 0 ; i < 10 ; i ++){
            MallOrder order = new MallOrder();
            order.setOrderName("standard中第"+i+"个订单");
            orderMapper.insert(order);
        }
    }

    /**
     * 范围查询:
     * Logic SQL: SELECT  id,order_name  FROM mall_order WHERE (id BETWEEN ? AND ?)
     * Actual SQL: db1 ::: SELECT  id,order_name  FROM mall_order_1 WHERE (id BETWEEN ? AND ?) ::: [1415550634731560961, 1415550634748338178]
     * Actual SQL: db1 ::: SELECT  id,order_name  FROM mall_order_2 WHERE (id BETWEEN ? AND ?) ::: [1415550634731560961, 1415550634748338178]
     * Actual SQL: db2 ::: SELECT  id,order_name  FROM mall_order_1 WHERE (id BETWEEN ? AND ?) ::: [1415550634731560961, 1415550634748338178]
     * Actual SQL: db2 ::: SELECT  id,order_name  FROM mall_order_2 WHERE (id BETWEEN ? AND ?) ::: [1415550634731560961, 1415550634748338178]
     *
     *
     * 使用inline模式是不支持范围查询的,standard可以按照算法提供的方法或表名库名进行范围查找
     */
    @Test
    public void queryDataByRang(){
        QueryWrapper<MallOrder> wrapper = new QueryWrapper<>();
        wrapper.between("id",1415550634731560961L,1415550634748338178L);
        List<MallOrder> mallOrders = orderMapper.selectList(wrapper);
        mallOrders.forEach(mallOrder -> System.out.println(mallOrder));
    }

}

 分库分表-complex模式-混合字段范围查询

  • 相同的sql和依赖和mapper省略
  • 配置文件
# 应用名称
spring.application.name=twodb-complex
#配置数据库别名:两个数据库
spring.shardingsphere.datasource.names=db1,db2
#第一个数据库 库名:test
spring.shardingsphere.datasource.db1.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.db1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.db1.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
spring.shardingsphere.datasource.db1.username=root
spring.shardingsphere.datasource.db1.password=root
#第二个数据库 库名:test2
spring.shardingsphere.datasource.db2.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.db2.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.db2.url=jdbc:mysql://localhost:3306/test2?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
spring.shardingsphere.datasource.db2.username=root
spring.shardingsphere.datasource.db2.password=root
#真实表有哪些
spring.shardingsphere.sharding.tables.product.actual-data-nodes=db$->{1..2}.product_$->{1..2}


#分片(分表:table-strategy)策略
#分片键ID:可以多个ID联合
spring.shardingsphere.sharding.tables.product.table-strategy.complex.sharding-columns=id,store_id
#分表算法(需自己实现):
spring.shardingsphere.sharding.tables.product.table-strategy.complex.algorithm-class-name=com.lixiunan.twodbcomplex.algorithm.MyComplexTableAlgorithm

#分片(分库:database-strategy)策略
#分片键ID:#分片键ID:
spring.shardingsphere.sharding.tables.product.database-strategy.complex.sharding-columns=id,store_id
#分库算法(需自己实现):
spring.shardingsphere.sharding.tables.product.database-strategy.complex.algorithm-class-name=com.lixiunan.twodbcomplex.algorithm.MyComplexDBAlgorithm
#显示sql语句
spring.shardingsphere.props.sql.show = true
spring.main.allow-bean-definition-overriding=true

自己实现存储&范围查找(库 + 表) 的策略

public class MyComplexDBAlgorithm implements ComplexKeysShardingAlgorithm<Long> {
    @Override
    public Collection<String> doSharding(Collection<String> availableTargetNames, ComplexKeysShardingValue<Long> shardingValue) {
        //获取店铺ID集合
        Collection<Long> storeIdCollection =
                shardingValue.getColumnNameAndShardingValuesMap().get("store_id");
        //创建新集合
        ArrayList<String> result = new ArrayList<String>();
        //策略为取摩尔
        for (Long storeId : storeIdCollection){
            BigInteger storeIdInteger = BigInteger.valueOf(storeId);
            BigInteger key =
                    (storeIdInteger.mod(new BigInteger("2"))).add(new BigInteger("1"));
            result.add("db"+key);
        }
        return result;
    }
}
public class MyComplexTableAlgorithm implements ComplexKeysShardingAlgorithm<Long> {
    @Override
    public Collection<String> doSharding(Collection<String> availableTargetNames, ComplexKeysShardingValue<Long> shardingValue) {
        //获取店铺ID集合
        Collection<Long> storeIdCollection =
                shardingValue.getColumnNameAndShardingValuesMap().get("store_id");
        //获取真实表前缀名称
        String logicTableName = shardingValue.getLogicTableName();
        //创建新集合
        ArrayList<String> result = new ArrayList<String>();
        //策略为取摩尔
        for (Long storeId : storeIdCollection){
            BigInteger storeIdInteger = BigInteger.valueOf(storeId);
            BigInteger key =
                    (storeIdInteger.mod(new BigInteger("2"))).add(new BigInteger("1"));
            result.add(logicTableName+"_"+key);
        }
        return result;
    }
}

 测试类——支持混合id范围条件查询

@RunWith(SpringRunner.class)
@SpringBootTest
public class TwodbComplexApplicationTests {
    @Resource
    private ProductMapper productMapper;
    @Resource
    private StoreMapper storeMapper;

    /**
     *添加数据
     */
    @Test
    public void add() {
        for(int i = 0 ; i < 10 ; i ++){
            Product product = new Product();
            Long idLong = Long.valueOf(202110L + i);
            product.setId(idLong);
            Long storeIdLong = Long.valueOf(676 + i);
            product.setStoreId(storeIdLong);
            product.setProductName("complex第"+i+"个商品");
            product.setProductStatus(((i % 2)+1)+"");
            productMapper.insert(product);
        }
    }

    /**
     * 缺少参数不能查询
     */
    @Test
    public void queryRange(){
        QueryWrapper<Product> wrapper = new QueryWrapper<>();
        wrapper.between("store_id",670L,680L);
        List<Product> products = productMapper.selectList(wrapper);
        products.forEach(product -> System.out.println(product));
    }

    /**
     * 支持(必须)混合ID复杂查询,如配置中的
     */
    @Test
    public void queryCourseComplex(){
        QueryWrapper<Product> wrapper = new QueryWrapper<>();
        wrapper.between("id",202100L,202114L);
        wrapper.eq("store_id",677L);
        List<Product> products = productMapper.selectList(wrapper);
        products.forEach(product -> System.out.println(product));
    }

}

 分库分表-hint模式-指定数据库/表

  • 相同的sql和依赖和mapper省略
  • 配置文件
# 应用名称
spring.application.name=twodb-hint
#配置数据库别名:两个数据库
spring.shardingsphere.datasource.names=db1,db2
#第一个数据库 库名:test
spring.shardingsphere.datasource.db1.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.db1.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.db1.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
spring.shardingsphere.datasource.db1.username=root
spring.shardingsphere.datasource.db1.password=root
#第二个数据库 库名:test2
spring.shardingsphere.datasource.db2.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.db2.driver-class-name=com.mysql.cj.jdbc.Driver
spring.shardingsphere.datasource.db2.url=jdbc:mysql://localhost:3306/test2?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
spring.shardingsphere.datasource.db2.username=root
spring.shardingsphere.datasource.db2.password=root
#真实表有哪些
spring.shardingsphere.sharding.tables.product.actual-data-nodes=db$->{1..2}.product_$->{1..2}
#使用雪花算法自动生成id/主键生成策略
spring.shardingsphere.sharding.tables.product.key-generator.column=id
spring.shardingsphere.sharding.tables.product.key-generator.type=SNOWFLAKE

#分片(分表:table-strategy)策略
#分片键ID:可以多个ID联合
#分表算法(需自己实现hint模式):
spring.shardingsphere.sharding.tables.product.table-strategy.hint.algorithm-class-name=com.lixiunan.twodbhint.algorithm.MyHintTableAlgorithm
#分片(分库:database-strategy)策略
#分片键ID:#分片键ID:
#分库算法:不指定
#显示sql语句
spring.shardingsphere.props.sql.show = true
spring.main.allow-bean-definition-overriding=true


自己实现如何制定表/库

/**
 * @Description : TODO hint可向指定表/库中添加/获取数据
 * @Author : lixiunan
 * @Date : 2021/7/19
 **/
public class MyHintTableAlgorithm implements HintShardingAlgorithm<Long> {
    @Override
    public Collection<String> doSharding(Collection<String> availableTargetNames, HintShardingValue<Long> shardingValue) {
        String key =
                shardingValue.getLogicTableName() + "_" + shardingValue.getValues().toArray()[0];
        if(availableTargetNames.contains(key)){
            return Arrays.asList(key);
        }
        throw new UnsupportedOperationException("找不到表");
    }
}

 测试

@RunWith(SpringRunner.class)
@SpringBootTest
public class TwodbHintApplicationTests {

    @Resource
    private ProductMapper productMapper;

    /**
     * 指定查询的表
     * SELECT  id,store_id,product_name,product_status  FROM product
     * Actual SQL: db1 ::: SELECT  id,store_id,product_name,product_status  FROM product_1
     * Actual SQL: db2 ::: SELECT  id,store_id,product_name,product_status  FROM product_1
     */
    @Test
    public void queryByHint1(){
        HintManager hintManager = HintManager.getInstance();
        hintManager.addTableShardingValue("product",1);
        List<Product> products = productMapper.selectList(null);
        products.forEach(product -> System.out.println(product));
        hintManager.close();
    }

    /**
     * Logic SQL: SELECT  id,store_id,product_name,product_status  FROM product
     * Actual SQL: db1 ::: SELECT  id,store_id,product_name,product_status  FROM product_2
     * Actual SQL: db2 ::: SELECT  id,store_id,product_name,product_status  FROM product_2
     */
    @Test
    public void queryByHint2(){
        HintManager hintManager = HintManager.getInstance();
        hintManager.addTableShardingValue("product",2);
        List<Product> products = productMapper.selectList(null);
        products.forEach(product -> System.out.println(product));
        hintManager.close();
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Java程序员调优

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值