framework-sharding-sphere

1.介绍

集成sharding-sphere + seata + framework-dynamic-datasource + aviator 的 framework

以framework-dynamic-datasource为基础构建

集成aviator目的是实现sharding-sphere对yml的三元运算符的支持 从而实现分库或者分表算法 yml 三元配置 省去 java类的配置实现

2.项目结构

framework-sharding-sphere
└─src
    └─main
        ├─java
        │  └─com
        │      └─yan
        │          ├─abstractinterface
        │          │  ├─config
        │          │  └─shardingAlgorithm
        │          ├─config
        │          │  └─dynamic
        │          │      └─Impl
        │          └─shardingsphere
        │              └─shardingAlgorithm
        └─resources
            └─META-INF
                └─services

3.pom

这里注意我的上一篇博客 关于dynamic-datasource

<?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>

    <groupId>com.yan</groupId>
    <artifactId>framework-sharding-sphere</artifactId>
    <version>${project-module.version}</version>


    <properties>
        <java.version>8</java.version>
        <project-module.version>0.0.1-SNAPSHOT</project-module.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>${java.version}</maven.compiler.source>
        <maven.compiler.target>${java.version}</maven.compiler.target>
        <!--2.4以下 Hoxton.SR12-2.2.7.RELEASE 2.4以上2021.0.5-2021.0.5.0 -->
        <alibaba-druid.version>1.2.22</alibaba-druid.version>
        <!--5.2.0该版本和drud存在冲突sql界面无法使用自动配置进入,
        com.alibaba.druid.spring.boot.autoconfigure.stat.DruidFilterConfiguration
        配置类filter  配置 和5.2.0版本自动配置存在空指针异常会导致服务无法启动
        -->
        <!--<shardingsphere.version>5.2.0</shardingsphere.version>-->
        <!--5.0.0-alpha 稳定版本-->
        <shardingsphere.version>5.0.0-alpha</shardingsphere.version>
        <dynamic-datasource.version>3.3.2</dynamic-datasource.version>
        <pagehelper-spring-boot-starter.version>1.2.13</pagehelper-spring-boot-starter.version>
        <mybatis-plus-spring-boot-starter.version>3.4.3</mybatis-plus-spring-boot-starter.version>

        <aviator.version>5.2.0</aviator.version>
        <commons-beanutils.version>1.9.4</commons-beanutils.version>
    </properties>


    <dependencies>
        <!--aviator-->
        <dependency>
            <groupId>com.googlecode.aviator</groupId>
            <artifactId>aviator</artifactId>
            <version>${aviator.version}</version>
        </dependency>
        <dependency>
            <groupId>commons-beanutils</groupId>
            <artifactId>commons-beanutils</artifactId>
            <version>${commons-beanutils.version}</version>
        </dependency>

        <!--分库分表-->
        <!-- ShardingSphere -->
        <!-- Sharding-JDBC -->
        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
            <version>${shardingsphere.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>shardingsphere-jdbc-core</artifactId>
            <version>${shardingsphere.version}</version>
        </dependency>
        <!-- ShardingSphere 对 seata 事务 模式 支持-->
        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>shardingsphere-transaction-core</artifactId>
            <version>${shardingsphere.version}</version>
        </dependency>
        <!--多数据源-->
        <dependency>
            <groupId>com.yan</groupId>
            <artifactId>framework-dynamic-datasource</artifactId>
            <version>${project-module.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>com.baomidou</groupId>
                    <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
            <version>${dynamic-datasource.version}</version>
        </dependency>
        <!--说明:1,为shardingsphere使用druid数据源时,不要使用: druid-spring-boot-starter这个包,
         因为它在会启动时自动从配置文件生成datasource,
         2.使用druid-spring-boot-starter这个包需要排除 com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure
         这个自动配置类,因为该自动配置类会生成datasource,从而保证druid监控界面可以正常使用
        所以在这里使用druid这个包-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>${alibaba-druid.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>com.alibaba</groupId>
                    <artifactId>druid</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>${alibaba-druid.version}</version>
        </dependency>

        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.22</version>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
            <version>2.5.0</version>
            <scope>compile</scope>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>RELEASE</version>
            <optional>true</optional>
        </dependency>
    </dependencies>
</project>

4.自定义算法使其支持yml的配置实现

com.yan.abstractinterface.shardingAlgorithm

4.1 AbstractIdShardingAlgorithm

package com.yan.abstractinterface.shardingAlgorithm;

import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.google.common.collect.Range;
import com.googlecode.aviator.AviatorEvaluator;
import lombok.SneakyThrows;
import org.apache.shardingsphere.sharding.api.sharding.standard.PreciseShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.RangeShardingValue;
import org.springframework.core.env.Environment;

import java.util.*;

/**
 * @Author yan
 * @Date 2024/12/6 23:29:43
 * @Description
 */
public interface AbstractIdShardingAlgorithm {
    interface ConstantShardingAlgorithm {
        String SPOT = ".";
        String PREFIX = "_";
        String SHARDING_ALGORITHMS_PATH = "spring.shardingsphere.rules.sharding.sharding-algorithms";
        String COLUMN_KEY = "column";
        String TABLE_INLINE_CUSTOM_KEY = "table-inline-custom";
        String CUSTOM_ALGORITHM_EXPRESSION_KEY = "custom-algorithm-expression";
        String ALGORITHM_EXPRESSION_KEY = "algorithm-expression";
        String PROPS_KEY = "props";
        String PROPS_PATH = SHARDING_ALGORITHMS_PATH + SPOT + TABLE_INLINE_CUSTOM_KEY + SPOT + PROPS_KEY;
        String CUSTOM_ALGORITHM_EXPRESSION_PATH = PROPS_PATH + SPOT + CUSTOM_ALGORITHM_EXPRESSION_KEY;
        String ALGORITHM_EXPRESSION_PATH = PROPS_PATH + SPOT + ALGORITHM_EXPRESSION_KEY;
        String TYPE = "CUSTOM_COMPLEX";
        String COLUMN_ID_VALUE = "id";

        static String replaceTableName(String logicTableName, String key) {
            if (key.startsWith(logicTableName)) {
                int index = key.indexOf(logicTableName);
                key = key.substring(index + logicTableName.length());
            }

            String keyStr = "$";
            if (key.contains(keyStr)) {
                int index = key.indexOf(keyStr);
                key = key.substring(0, index);
            }
            return key;
        }

        static String replaceReal(String expression) {
            String prefixStr = "{";
            String suffixStr = "}";
            if (expression.startsWith(prefixStr) && expression.endsWith(suffixStr)) {
                // 找到第一个 { 和 } 的位置
                int start = expression.indexOf(prefixStr);
                int end = expression.lastIndexOf(suffixStr);
                expression = expression.substring(start + 1, end);
            }
            return expression;
        }
    }

    default String shardingSuffix(String logicTableName, Long idValue) {
        return shardingSuffix(logicTableName, (Object) idValue);
    }

    /**
     * 精确路由算法
     *
     * @param availableTargetNames 可用的表列表(配置文件中配置的 actual-data-nodes会被解析成 列表被传递过来)
     * @param shardingValue        精确的值
     * @return 结果表
     */
    default String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Long> shardingValue) {
        Long idValue = shardingValue.getValue();
        // 根据精确值获取路由表
        String logicTableName = shardingValue.getLogicTableName();
        String actuallyTableName = logicTableName + shardingSuffix(logicTableName, idValue);
        if (availableTargetNames.contains(actuallyTableName)) {
            return actuallyTableName;
        }
        return null;
    }


    /**
     * 范围路由算法
     *
     * @param availableTargetNames 可用的表列表(配置文件中配置的 actual-data-nodes会被解析成 列表被传递过来)
     * @param shardingValue        值范围
     * @return 路由后的结果表
     */
    default Collection<String> doSharding(Collection<String> availableTargetNames, RangeShardingValue<Long> shardingValue) {
        // 获取到范围查找的最小值,如果条件中没有最小值设置为 tableLowerDate
        Range<Long> valueRange = shardingValue.getValueRange();
        Long rangeLowerValue = valueRange.hasLowerBound() ? valueRange.lowerEndpoint() : 0l;
        Long rangeUpperValue = valueRange.hasUpperBound() ? valueRange.upperEndpoint() : Long.MAX_VALUE;

        // 根据范围值获取路由表
        List<String> tableNames = new ArrayList<>();
        // 过滤那些存在的表
        String logicTableName = shardingValue.getLogicTableName();

        while (rangeLowerValue > rangeUpperValue) {
            String actuallyTableName = logicTableName + shardingSuffix(logicTableName, rangeLowerValue);
            if (availableTargetNames.contains(actuallyTableName)) {
                tableNames.add(actuallyTableName);
            }
            rangeLowerValue++;
        }
        return tableNames;
    }

    /**
     * 泛型 ============
     *
     * @param logicTableName
     * @param idValue
     * @param <T>
     * @return
     */

    @SneakyThrows
    default <T> String shardingSuffix(String logicTableName, T idValue) {
        String expression = StrUtil.EMPTY;
        String prefix = ConstantShardingAlgorithm.PREFIX;
        Environment env = SpringUtil.getBean(Environment.class);
        String spot = ConstantShardingAlgorithm.SPOT;
        String column = env.getProperty(ConstantShardingAlgorithm.PROPS_PATH + spot + ConstantShardingAlgorithm.COLUMN_KEY);
        column = StrUtil.isBlank(column) ? ConstantShardingAlgorithm.COLUMN_ID_VALUE : column;
        expression = env.getProperty(ConstantShardingAlgorithm.PROPS_PATH + spot + ConstantShardingAlgorithm.CUSTOM_ALGORITHM_EXPRESSION_KEY);

        if (StrUtil.isBlank(expression)) {
            String algorithmExpression = env.getProperty(ConstantShardingAlgorithm.PROPS_PATH + spot + ConstantShardingAlgorithm.ALGORITHM_EXPRESSION_KEY);
            if (StrUtil.isBlank(algorithmExpression)) {
                throw new Exception(ConstantShardingAlgorithm.ALGORITHM_EXPRESSION_KEY + " is not null");
            }
            String[] split = algorithmExpression.split("->");
            String prefixTable = split[0];
            prefix = ConstantShardingAlgorithm.replaceTableName(logicTableName, prefixTable);
            expression = ConstantShardingAlgorithm.replaceReal(split[split.length - 1]);
        }

        if (StrUtil.isBlank(expression)) {
            throw new Exception("expression is null");
        }

        expression = ConstantShardingAlgorithm.replaceTableName(logicTableName, expression);
        expression = ConstantShardingAlgorithm.replaceReal(expression);

        Map<String, Object> map = new LinkedHashMap<>();
        map.put(column, idValue);

        String execute = "";
        try {
            Object executeReturn = AviatorEvaluator.execute(expression, map);
            execute = prefix + executeReturn;
        } catch (Exception e) {
            throw new Exception("分片算法执行失败");
        }
        return execute;
    }

    /**
     * 精确路由算法
     *
     * @param availableTargetNames 可用的表列表(配置文件中配置的 actual-data-nodes会被解析成 列表被传递过来)
     * @param shardingValue        精确的值
     * @return 结果表
     */
    default <T extends Comparable<?>> String doShardingOne(Collection<String> availableTargetNames, PreciseShardingValue<T> shardingValue) {
        T idValue = shardingValue.getValue();
        // 根据精确值获取路由表
        String logicTableName = shardingValue.getLogicTableName();
        String actuallyTableName = logicTableName + shardingSuffix(logicTableName, idValue);
        if (availableTargetNames.contains(actuallyTableName)) {
            return actuallyTableName;
        }
        return null;
    }

    /**
     * 范围路由算法
     *
     * @param availableTargetNames 可用的表列表(配置文件中配置的 actual-data-nodes会被解析成 列表被传递过来)
     * @param shardingValue        值范围
     * @return 路由后的结果表
     */
    default <T extends Comparable<?>> Collection<String> doShardingList(Collection<String> availableTargetNames, RangeShardingValue<T> shardingValue) {
        // 获取到范围查找的最小值,如果条件中没有最小值设置为 tableLowerDate
        Range<T> valueRange = shardingValue.getValueRange();
        Long rangeLowerValue = Long.parseLong(String.valueOf(valueRange.hasLowerBound() ? valueRange.lowerEndpoint() : 0l));
        Long rangeUpperValue = Long.parseLong(String.valueOf(valueRange.hasUpperBound() ? valueRange.upperEndpoint() : Long.MAX_VALUE));

        // 根据范围值获取路由表
        List<String> tableNames = new ArrayList<>();
        // 过滤那些存在的表
        String logicTableName = shardingValue.getLogicTableName();

        while (rangeLowerValue > rangeUpperValue) {
            String actuallyTableName = logicTableName + shardingSuffix(logicTableName, (T) rangeLowerValue);
            if (availableTargetNames.contains(actuallyTableName)) {
                tableNames.add(actuallyTableName);
            }
            rangeLowerValue++;
        }
        return tableNames;
    }
}

4.2 实现AbstractIdShardingAlgorithm==> IdCustomShardingAlgorithm

com.yan.shardingsphere.shardingAlgorithm

IdCustomShardingAlgorithm

package com.yan.shardingsphere.shardingAlgorithm;

import cn.hutool.core.util.StrUtil;
import com.googlecode.aviator.AviatorEvaluator;
import com.yan.abstractinterface.shardingAlgorithm.AbstractIdShardingAlgorithm;
import groovy.util.logging.Slf4j;
import lombok.SneakyThrows;
import org.apache.shardingsphere.sharding.api.sharding.standard.PreciseShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.RangeShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.StandardShardingAlgorithm;

import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;

/**
 * @Author yan
 * @Date 2024/12/5 20:54:54
 * @Description //自定义分片策略
 */
@Slf4j
public class IdCustomShardingAlgorithm implements AbstractIdShardingAlgorithm, StandardShardingAlgorithm<Long> {
    private Properties props = new Properties();

    /**
     * 返回算法类型,用于标识分片算法。
     *
     * @return 算法类型字符串
     */
    @Override
    public String getType() {
        return ConstantShardingAlgorithm.TYPE; // 自定义算法类型
    }

    /**
     * 初始化方法,可用于加载配置(如果需要)。
     */
    @Override
    public void init() {
    }


    @Override
    public Properties getProps() {
        return props;
    }

    @Override
    public void setProps(Properties properties) {
        this.props = properties;
    }

    @SneakyThrows
    @Override
    public String shardingSuffix(String logicTableName, Long idValue) {
        String expression = StrUtil.EMPTY;
        String prefix = ConstantShardingAlgorithm.PREFIX;

        String column = props.getProperty(ConstantShardingAlgorithm.COLUMN_KEY);
        column = StrUtil.isBlank(column) ? ConstantShardingAlgorithm.COLUMN_ID_VALUE : column;
        expression = props.getProperty(ConstantShardingAlgorithm.CUSTOM_ALGORITHM_EXPRESSION_KEY);

        if (StrUtil.isBlank(expression)) {
            String algorithmExpression = props.getProperty(ConstantShardingAlgorithm.ALGORITHM_EXPRESSION_KEY);
            if (StrUtil.isBlank(algorithmExpression)) {
                throw new Exception(ConstantShardingAlgorithm.ALGORITHM_EXPRESSION_KEY + " is not null");
            }
            String[] split = algorithmExpression.split("->");
            String prefixTable = split[0];
            prefix = ConstantShardingAlgorithm.replaceTableName(logicTableName, prefixTable);
            expression = ConstantShardingAlgorithm.replaceReal(split[split.length - 1]);
        }

        if (StrUtil.isBlank(expression)) {
            throw new Exception("expression is null");
        }

        expression = ConstantShardingAlgorithm.replaceTableName(logicTableName, expression);
        expression = ConstantShardingAlgorithm.replaceReal(expression);

        Map<String, Object> map = new LinkedHashMap<>();
        map.put(column, idValue);

        String execute = "";
        try {
            Object executeReturn = AviatorEvaluator.execute(expression, map);
            execute = prefix + executeReturn;
        } catch (Exception e) {
            throw new Exception("分片算法执行失败");
        }
        return execute;
    }

    /**
     * 精确路由算法
     *
     * @param availableTargetNames 可用的表列表(配置文件中配置的 actual-data-nodes会被解析成 列表被传递过来)
     * @param shardingValue        精确的值
     * @return 结果表
     */
    @Override
    public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Long> shardingValue) {
        return AbstractIdShardingAlgorithm.super.doSharding(availableTargetNames, shardingValue);
    }


    /**
     * 范围路由算法
     *
     * @param availableTargetNames 可用的表列表(配置文件中配置的 actual-data-nodes会被解析成 列表被传递过来)
     * @param shardingValue        值范围
     * @return 路由后的结果表
     */
    @Override
    public Collection<String> doSharding(Collection<String> availableTargetNames, RangeShardingValue<Long> shardingValue) {
        return AbstractIdShardingAlgorithm.super.doSharding(availableTargetNames, shardingValue);
    }

}

5. AbstractDynamicDataSource 实现(可选)

当然也可以不实现,直接使用DefaultDynamicDataSourceImpl 就行

package com.yan.config.dynamic.Impl;

import com.yan.abstractinterface.config.dynamic.AbstractDynamicDataSource;
import org.springframework.stereotype.Service;

/**
 * @Author yan
 * @Date 2024/10/25 上午9:21:31
 * @Description
 */
@Service
public class ShardingSphereDynamicDataSourceImpl implements AbstractDynamicDataSource {
}

6.resources配置

在resources.META-INF.services下

新建文件org.apache.shardingsphere.sharding.spi.ShardingAlgorithm

文件内容:

com.yan.shardingsphere.shardingAlgorithm.IdCustomShardingAlgorithm

6.1基础yml配置

application.yml

spring:
  main:
    allow-circular-references: true
    allow-bean-definition-overriding: true #当遇到同样名字的时候,是否允许覆盖注册
####################################################################################################################################################################
  autoconfigure:
    exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure  #去除druid配置
  datasource:
####################################################################################################################################################################
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      filter:
        stat:
          enabled: true
      stat-view-servlet:
        enabled: true
        loginUsername: admin
        loginPassword: 123456
      web-stat-filter:
        enabled: true
    dynamic:
      druid:
        # 初始化连接数
        initialSize: 10
        # 最小连接池数量
        minIdle: 20
        # 最大连接池数量
        maxActive: 100
        # 配置连接等待超时的时间,单位为毫秒
        maxWait: 60000
        # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
        timeBetweenEvictionRunsMillis: 60000
        # 配置一个连接在池中最小生存的时间,单位是毫秒
        minEvictionIdleTimeMillis: 300000
        # 配置一个连接在池中最大生存的时间,单位是毫秒
        maxEvictionIdleTimeMillis: 900000
        # 配置检测连接是否有效
        validationQuery: SELECT 1 FROM DUAL
        # testOnBorrow 能够确保我们每次都能获取到可用的连接,但是如果设置为 true,则每次获取连接时候都要到数据库验证连接有效性,这在高并发的时候会造成性能下降,
        # 可以将 testOnBorrow 设置成 false,testWhileIdle 设置成 true 这样能获得比较好的性能
        testWhileIdle: true
        testOnBorrow: false
        # testOnBorrow 和 testOnReturn 在生产环境一般是不开启的,主要是性能考虑。
        testOnRetrun: false
####################################################################################################################################################################
  # sharding-sphere 数据源 公共配置
  shardingsphere:
    datasource:
      common:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        initial-size: ${spring.datasource.dynamic.druid.initialSize}
        min-idle: ${spring.datasource.dynamic.druid.minIdle}
        maxActive: ${spring.datasource.dynamic.druid.maxActive}
        # 配置获取连接等待超时的时间
        maxWait: ${spring.datasource.dynamic.druid.maxWait}
        # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
        timeBetweenEvictionRunsMillis: ${spring.datasource.dynamic.druid.timeBetweenEvictionRunsMillis}
        # 配置一个连接在池中最小生存的时间,单位是毫秒
        minEvictableIdleTimeMillis: ${spring.datasource.dynamic.druid.minEvictionIdleTimeMillis}
        #Oracle需要打开注释
        #validationQuery: ${spring.datasource.dynamic.druid.validationQuery}
        testWhileIdle: ${spring.datasource.dynamic.druid.testWhileIdle}
        testOnBorrow: ${spring.datasource.dynamic.druid.testOnBorrow}
        testOnReturn: ${spring.datasource.dynamic.druid.testOnReturn}
        # 打开PSCache,并且指定每个连接上PSCache的大小
        poolPreparedStatements: true
        maxPoolPreparedStatementPerConnectionSize: 20
        # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
        filters: stat,wall,slf4j
        # 通过connectProperties属性来打开mergeSql功能;慢SQL记录
        connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
        wall:
          multi-statement-allow: true
#================================================================================================================================================================================
# mybatis plus 配置
#================================================================================================================================================================================
mybatis-plus:
  # 设置Mapper文件位置
  mapper-locations: classpath:mapper/*.xml, classpath:mapper/**/*.xml
  #配置
  configuration:
    log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl
    # 使用JDBC的getGeneratedKeys,获取数据库自增主键值
    use-generated-keys: true
    # 使用列别名
    use-column-label: true
    # 驼峰下划线转换
    map-underscore-to-camel-case: true

logging:
  level:
    com.yan.dao: debug
#================================================================================================================================================================================
sharding:
  transaction:
    seata:
      at:
        enable: true
client:
  application:
    id: archetype
  transaction:
    service:
      group: default_tx_group

6.2 demo.yml:

#使用 该配置如报错请注释DynamicDataSourceConfig,AbstractDynamicDataSource 配置类  和依赖 dynamic-datasource 和@DS 注解 多数据源配置
spring:
  shardingsphere:
    props:
      sql-show: true
    datasource:
      names: sharding
      sharding:
        type: ${spring.shardingsphere.datasource.common.type}
        driver-class-name: ${spring.shardingsphere.datasource.common.driver-class-name}
        #使用 druid  jdbc-url替换url
#        type: com.alibaba.druid.pool.DruidDataSource
        url: jdbc:mysql://127.0.0.1:3306/sharding?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&allowMultiQueries=true
#        type: com.zaxxer.hikari.HikariDataSource
#        jdbc-url: jdbc:mysql://127.0.0.1:3306/dev?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&allowMultiQueries=true
#        driver-class-name: com.mysql.cj.jdbc.Driver
        username: username
        password: password
    rules:
      sharding:
        sharding-algorithms:
          # 分表算法
          table-inline:
            type: INLINE
            props:
              algorithm-expression: sys_user_$->{id % 2}
          table-inline-02:
            type: INLINE
            props:
              #有效 这种三元写法 原生是不支持的 IdCustomShardingAlgorithm 已经支持完善
              algorithm-expression: sys_user_$->{(id<10?0:(id>20?0:1))}
          table-inline-custom:
            type: CUSTOM_COMPLEX
            props:
              #有效
              column: id
              algorithm-expression: sys_user_$->{(id % 2)}
#              custom-algorithm-expression: (id<10?0:(id>20?0:1))

          # 分库算法 只分表不使用
#          database-inline:
#            type: INLINE
#            props:
#              algorithm-expression: ds$->{sharding_key % 2}

        tables:
          sys_user2_s:
            actual-data-nodes: sharding.sys_user_$->{0..1}
            key-generate-strategy:
              column: id
              key-generator-name: snowflake
            # 分库策略 只分表不使用
#            database-strategy:
#              standard:
#                sharding-column: sharding_key
#                sharding-algorithm-name: database-inline
            # 分表策略
            table-strategy:
              standard:
                sharding-column: id
                sharding-algorithm-name: table-inline
          sys_user:
            # 实际数据节点
            actual-data-nodes: sharding.sys_user_$->{0..1}
            key-generate-strategy:
              column: id
              key-generator-name: snowflake
            # 表分片策略,指定分片列和自定义算法类
            table-strategy:
              standard:
                sharding-column: id
#                algorithm-class-name:
                sharding-algorithm-name: table-inline-custom
#              complex:
#                sharding-columns: id
#                algorithm-class-name: com.yan.shardingsphere.shardingAlgorithm.IdBasedShardingAlgorithm

        key-generators:
          snowflake:
            type: SNOWFLAKE
            props:
              worker-id: 1
#    mode:
#      type: Standalone
#      repository:
#        type: File
#      overwrite: true