1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/dragonyeah-shardingsphere-5.5.0-example

Клонировать/Скачать
README.md 49 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
Отправлено 07.06.2025 08:55 8bac5c5

shardingsphere-5.5.0-example

Ссылка на официальный сайт: https://shardingsphere.apache.org/


Введение

Из-за отсутствия информации о том, как интегрировать версию shardingsphere-5.5.0 с springboot3.x, все примеры, доступные в интернете, используют локальные конфигурации данных. Однако в реальных условиях мы используем удаленные конфигурационные центры, такие как jdbc:shardingsphere:classpath:sharding.yaml. Этот подход не подходит для корпоративных приложений. Поэтому я создал этот интеграционный проект, чтобы решить эти конфигурационные проблемы.

Решаемые проблемы:

  1. Удаленная конфигурация: с помощью реализации SPI, используя конфигурационный центр Nacos, для удаленной конфигурации источников данных, что позволяет реализовать разделение на чтение и запись, а также разделение на базы данных и таблицы.

  2. Автоматизация конфигурации: из-за необходимости постоянного изменения конфигураций для разделения на базы данных и таблицы, конфигурационные файлы становятся очень большими и сложными. Поэтому я внедрил автоматическое сканирование пакетов и генерацию конфигурационных файлов с помощью аннотаций, что значительно упрощает конфигурационный процесс.

Я всего лишь помощник, приветствую ваши отзывы и предложения по улучшению проекта

Интеграционный проект

springboot3.x + shardingsphere-5.5.0 + nacos-2.3.0 + mybatis-plus#### Требуемая среда: jdk17/jdk21 + mysql8.0

Структура проекта

  shardingsphere5-example
  |- example-common  Общие конфигурации mybatis-plus
  |- local-mode-5.5.0  Локальная конфигурация
  |- nacos-mode-5.5.0  Конфигурация через Nacos

  зависимости 
  |- parent.pom  Основной файл зависимостей Maven
  |- скрипты
     |- Скрипты для базы данных

Интеграция springboot3.x с web-приложением здесь не рассматривается подробно, смотрите код. Основное внимание уделено способу включения shardingsphere-5.5.0 и его конфигурации.

Конфигурация shardingsphere5.X

Способ конфигурации shardingsphere5.X отличается от предыдущих версий. В shardingsphere5.X используется оригинальный драйвер org.apache.shardingsphere.driver.ShardingSphereDriver, и конфигурация источников данных и разделения на базы данных и таблицы осуществляется с помощью spring.datasource.url=jdbc:shardingsphere:classpath:sharding.yaml. Пример конфигурации:sharding.yaml```yaml источники_данных: ds_0: driverClassName: com.mysql.cj.jdbc.Driver dataSourceClassName: com.zaxxer.hikari.HikariDataSource url: jdbc:mysql://localhost:3306/db_sequence_0?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true username: root password: root ds_1: driverClassName: com.mysql.cj.jdbc.Driver dataSourceClassName: com.zaxxer.hikari.HikariDataSource url: jdbc:mysql://localhost:3306/db_sequence_1?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true username: root password: root свойства: sql-show: true

Структура представлена на следующем рисунке:
![local-config.png](script%2Fimages%2Flocal-config.png)Конфигурация локального режима довольно проста, [application.yaml](local-mode-5.5.0%2Fsrc%2Fmain%2Fresources%2Fapplication.yaml)

```yaml
server:
  port: 8088
  servlet:
    context-path: /
    encoding:
      force-response: true

spring:
  profiles:
    active: dev
  main:
    allow-bean-definition-overriding: true
  application:
    name: local-mode
  datasource:
    driver-class-name: org.apache.shardingsphere.driver.ShardingSphereDriver
    url: jdbc:shardingsphere:classpath:sharding.yaml
  servlet:
    multipart:
      max-file-size: 100MB
      max-request-size: 100MB


# Конфигурация MyBatisPlus
# https://baomidou.com/config/
mybatis-plus:
  # Множественные пакеты, например com.base.**.mapper,org.xxx.**.mapper
  mapperPackage: com.base.**.mapper
  # Путь к соответствующим XML файлам
  mapperLocations: classpath*:mapper/**/*Mapper.xml
  # Пакеты для сканирования сущностей, несколько пакетов разделены запятыми или точками с запятой
  typeAliasesPackage: com.base.**.domain
  global-config:
    dbConfig:
      # Тип первичного ключа
      # AUTO - автоинкремент, NONE - пустое значение, INPUT - ввод пользователем, ASSIGN_ID - уникальный идентификатор, ASSIGN_UUID - уникальный UUID
      # Если требуется изменить на автоинкремент, необходимо настроить все таблицы базы данных на автоинкремент
      idType: ASSIGN_ID

Основные настройки включают:

spring:
  datasource:
    driver-class-name: org.apache.shardingsphere.driver.ShardingSphereDriver
    url: jdbc:shardingsphere:classpath:sharding.yaml

Используем способ jdbc:shardingsphere:classpath:sharding.yaml для подключения к источнику данных и настройки шардинга.### Конфигурация Nacos nacos-mode-5.5.0

Мы используем центр конфигурации Nacos для реализации удаленной конфигурации, чтения и записи, а также шардинга. Структура представлена на следующем рисунке: nacos-config.png> Просто посмотрим на конфигурацию:

  • Это локальный файл конфигурации bootstrap.yaml
nacos:
  namespace: ecommerce-local
  group: MALL_GROUP
  service-address: 192.168.8.166:8848
  username: nacos
  password: nacos

spring:
  profiles:
    active: local
  application:
    name: nacos-mode
  main:
    allow-circular-references: true
    allow-bean-definition-overriding: true
  cloud:
    nacos:
      config:
        server-addr: ${nacos.service-address}
        file-extension: yaml
        namespace: ${nacos.namespace}
        group: ${nacos.group}
        username: ${nacos.username}
        password: ${nacos.password}
      discovery:
        server-addr: ${nacos.service-address}
        namespace: ${nacos.namespace}
        group: ${nacos.group}
        username: ${nacos.username}
        password: ${nacos.password}
  datasource:
    driver-class-name: org.apache.shardingsphere.driver.ShardingSphereDriver
    url: jdbc:shardingsphere:nacos:sharding.yaml?serverAddr=${nacos.service-address}&namespace=${nacos.namespace}&group=${nacos.group}&username=${nacos.username}&password=${nacos.password}

В центре конфигурации Nacos есть два файла

    1. Конфигурация проекта: nacos-mode.yaml
server:
  port: 8088
  servlet:
    context-path: /
    encoding:
      force-response: true
```# Конфигурация Spring
spring:
  servlet:
    multipart:
      max-file-size: 100MB
      max-request-size: 100MB

Конфигурация MyBatisPlus

https://baomidou.com/config/

mybatis-plus:

Использование нескольких пакетов, например com.base.admin..mapper,org.xxx..mapper

mapperPackage: com.base.**.mapper

Путь к соответствующим XML файлам

mapperLocations: classpath*:mapper/**/*Mapper.xml

Сканирование сущностей, несколько пакетов разделены запятыми или точками с запятой

typeAliasesPackage: com.base.**.domain global-config: dbConfig: # Тип первичного ключа # AUTO - автоинкремент NONE - пустое значение INPUT - ввод пользователем ASSIGN_ID - снежныйflake ASSIGN_UUID - уникальный UUID # Если требуется изменить на автоинкремент, необходимо установить все таблицы базы данных на автоинкремент idType: ASSIGN_ID

> Единственное отличие заключается в изменении конфигурации на URL: jdbc:shardingsphere:nacos:sharding.yaml?serverAddr=${nacos.service-address}&namespace=${nacos.namespace}&group=${nacos.group}&username=${nacos.username}&password=${nacos.password}

# Реализация загрузки конфигурации ShardingSphereURLLoader
> По результатам анализа, classpath:sharding.yaml реализует загрузку sharding.yaml из проекта, а мы можем предположить, что если бы мы определили nacos:sharding.yaml, то конфигурация могла бы загружаться из центра конфигураций Nacos.

* 1. Исследуя исходный код ShardingSphere, было обнаружено, что classpath: загружается с помощью SPI (ClassPathURLLoader), интегрированного с ShardingSphereURLLoader. Поэтому мы можем использовать ClassPathURLLoader как пример для реализации CustomNacosURLLoader, чтобы достичь загрузки sharding.yaml из центра конфигураций Nacos.

* 2. Реализация SPI: [CustomNacosURLLoader.java](nacos-mode-5.5.0%2Fsrc%2Fmain%2Fjava%2Fcom%2Fbase%2Fspi%2FCustomNacosURLLoader.java)
````java
package com.base.spi;

import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.common.Constants;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.shaded.com.google.common.base.Preconditions;
import lombok.SneakyThrows;
import org.apache.shardingsphere.infra.url.spi.ShardingSphereURLLoader;

import java.util.Properties;

/**
 * @title: CustomNacosURLLoader
 * @description: Реализация SPI для чтения удаленной конфигурации Nacos
 * @author: arron
 * @date: 2024/8/28 22:09
 */
public class CustomNacosURLLoader implements ShardingSphereURLLoader {
```    /**
     * Определение типа после jdbc:shardingsphere: как nacos:
     */
    private static final String NACOS_TYPE = "nacos:";    /**
     * Принимает параметры после nacos: в формате sharding.yaml?serverAddr=${nacos.service-address}&namespace=${nacos.namespace}&group=${nacos.group}&username=${nacos.username}&password=${nacos.password}
     * @param configurationSubject идентификатор конфигурации dataId
     * @param queryProps параметры URL, уже распаршенные в объект Properties
     * @return конфигурацию
     */
    @Override
    @SneakyThrows
    public String load(String configurationSubject, Properties queryProps) {
        ConfigService configService = NacosFactory.createConfigService(queryProps);
        String dataId = configurationSubject;
        // Получает конфигурацию из Nacos
        String config = configService.getConfig(dataId, queryProps.getProperty(Constants.GROUP, Constants.DEFAULT_GROUP), 500);
        Preconditions.checkArgument(config != null, "Конфигурация Nacos [" + dataId + "] пуста.");
        return config;
    }
```java
    @Override
    public Object getType() {
        return NACOS_TYPE;
    }
}
```* 3. Декларация SPI: В папке resources проекта создайте файл: META-INF/services/org.apache.shardingsphere.infra.url.spi.ShardingSphereURLLoader
  и добавьте следующее содержимое: com.base.spi.CustomNacosURLLoader (реализация SPI)

---
# Тестирование:

http://localhost:8088/list?shardingKey=1

![test.png](script%2Fimages%2Ftest.png)


# Настройка параметров для распределения по базам данных и таблицам

## 1. Настройка конфигурации:

![sharding_table.png](script%2Fimages%2Fsharding_table.png)

````yaml
sequence_mode: # sequence - стратегия распределения по таблицам
  type: CLASS_BASED
  props:
    strategy: STANDARD
    algorithmClassName: com.base.strategy.StandardTablePreciseStandardShardingAlgorithm
    expression: SHARDING_KEY % 4 * 8 + SHARDING_KEY * 2 + SHARDING_KEY / 8 # пользовательская формула распределения по таблицам

2. Добавление метода инициализации в реализующий класс, принимающего пользовательские параметры

/**
 * @title: Стратегия распределения по таблицам
 * @description: Точная стратегия распределения по таблицам
 * @author: arron
 * @date: 2024/8/25 11:57
 */
public class TablePreciseShardingAlgorithm implements StandardShardingAlgorithm<Long> {

    /**
     * Значение по умолчанию
     */
    private static String SHARDING_KEY = "SHARDING_KEY";

    /**
     * Пользовательские параметры
     */
    private Properties properties;

    @Override
    public void init(Properties properties) {
        this.properties = properties;
    }
}
````    /**
     * Вычисление значения для распределения по таблицам
     *
     * @param preciseShardingValue
     * @return
     */
    private int getShardingValue(long preciseShardingValue) {
        String expression = properties.getProperty("expression");
        String expressionStr = expression.replace(SHARDING_KEY, String.valueOf(preciseShardingValue));
        // Выполнение вычисления
        int value = ExpressionEvaluator.evaluateExpression(expressionStr);
        return value;
    }```java
    @Override
    public String doSharding(Collection<String> tables, PreciseShardingValue<Long> preciseShardingValue) {
        int value = getShardingValue(preciseShardingValue.getValue().longValue());

        String tableName = null;
        for (String table : tables) {
            if (table.endsWith(String.valueOf(value))) {
                tableName = table;
                break;
            }
        }
        if (StringUtils.isBlank(tableName)) {
            throw new IllegalArgumentException("Ошибка получения имени таблицы по стратегии распределения по таблицам");
        }
        return tableName;
    }
```

```markdown
## Множественные ключи для шардинга

```java
/**
 * @Override
 */
public Collection<String> doSharding(Collection<String> tables, RangeShardingValue<Long> rangeShardingValue) {
    int size = tables.size();
    Set<String> result = new LinkedHashSet<>();
    // Начальное значение для between и
    long lower = rangeShardingValue.getValueRange().lowerEndpoint();
    long upper = rangeShardingValue.getValueRange().upperEndpoint();
    // Цикл для вычисления логики шардинга
    for (long i = lower; i <= upper; i++) {
        for (String table : tables) {
            if (table.endsWith(String.valueOf(i % size))) {
                result.add(table);
            }
        }
    }
    return result;
}
}
```

# Стратегия шардинга с множественными ключами

1. Реализация `ComplexKeysShardingAlgorithm` для шардинга по множественным ключам
````java
/**
 * @title: AbsComplexKeysShardingAlgorithm
 * @description: Стратегия шардинга с множественными ключами
 * @author: arron
 * @date: 2024/9/1 10:34
 */
@Slf4j
public abstract class AbsComplexKeysShardingAlgorithm implements ComplexKeysShardingAlgorithm<Long> {
    protected Properties properties;

    @Override
    public void init(Properties properties) {
        this.properties = properties;
    }
```    /**
     * Вычисление таблиц для шардинга
     *
     * @param columnNameAndShardingValuesMap
     * @return -1 если выражение отсутствует
     */
    protected int getShardingValue(Map<String, Collection<Long>> columnNameAndShardingValuesMap) {
        String expression = properties.getProperty("expression");
        if (StringUtils.isBlank(expression)) {
            log.error("expression_is_null");
            return -1;
        }
        Set<String> columnNameKeySet = columnNameAndShardingValuesMap.keySet();
        for (String columnName : columnNameKeySet) {
            Object preciseShardingValue = columnNameAndShardingValuesMap.get(columnName).iterator().next();
            expression = expression.replace(columnName, String.valueOf(preciseShardingValue));
        }
        // Выполнение вычисления
        int value = ExpressionEvaluator.evaluateExpression(expression);
        return value;
    }```markdown
}

/**
 * @title: ComplexKeysTableShardingAlgorithm
 * @description: Стратегия шардинга с множественными ключами для таблиц
 * @author: arron
 * @date: 2024/9/1 10:41
 */
@Slf4j
public class ComplexKeysTableShardingAlgorithm extends AbsComplexKeysShardingAlgorithm {
```java
    @Override
    public Collection<String> doSharding(Collection<String> tables, ComplexKeysShardingValue<Long> complexKeysShardingValue) {
        if (CollectionUtils.isEmpty(tables)) {
            log.error("ComplexKeysTableShardingAlgorithm_tables_is_null");
            throw new IllegalArgumentException("ComplexKeysTableShardingAlgorithm_tables_is_null");
        }
        Collection<String> result = new LinkedHashSet<>();
        String tableName = null;

        if (tables.size() == 1) {
            log.error("ComplexKeysTableShardingAlgorithm_tables_size_is_one");
            tableName = tables.iterator().next();
            result.add(tableName);
            return result;
        }

        Map<String, Collection<Long>> columnNameAndShardingValuesMap = complexKeysShardingValue.getColumnNameAndShardingValuesMap();
        int value = getShardingValue(columnNameAndShardingValuesMap);

        for (String table : tables) {
            if (table.endsWith(String.valueOf(value))) {
                tableName = table;
                result.add(tableName);
                break;
            }
        }

        if (result.isEmpty()) {
            log.error("ComplexKeysTableShardingAlgorithm_tableName_error Согласно стратегии шардинга по ключу шардинга, ошибка получения имени таблицы");
            throw new IllegalArgumentException("ComplexKeysTableShardingAlgorithm_tableName_error Согласно стратегии шардинга по ключу шардинга, ошибка получения имени таблицы");
        }
        return result;
    }
}

```
Конфигурационный файл: [sharding-complex-bak.yaml](local-mode-5.5.0%2Fsrc%2Fmain%2Fresources%2Fsharding-bak.yaml)
![img_1.png](script/images/complex-config.png)
```````yaml
rules:
  - !SHARDING
    tables: # Логика шардинга
      sequence:
        tableStrategy:
          complex:
            shardingColumns: sharding_key, value
            shardingAlgorithmName: table_sequence_mode
    shardingAlgorithms: # Стратегия алгоритмов шардинга
      table_sequence_mode: # Стратегия шардинга для sequence
        type: CLASS_BASED
        props:
          strategy: COMPLEX
          algorithmClassName: com.base.strategy.ComplexKeysTableShardingAlgorithm
          expression: sharding_key % 4 + value / 19000

Автоматическая конфигурация

Шаг 1: Определите аннотацию класса, сделайте ключевые конфигурации атрибутами, позволяющими пользователям выполнять настройку, как показано ниже: См. класс: ShardingConfig.java

```java
@ShardingConfig(
        shardingColumn = "sharding_key",
        tbAlgorithmsType = ShardingConfigEnums.ShardingAlgorithmType.CLASS_BASED,
        tbStrategy = ShardingConfigEnums.ShardingStrategy.STANDARD,
        tbAlgorithmClassName = "com.base.strategy.StandardTablePreciseStandardShardingAlgorithm",
        tbExpression = "sharding_key%4",
        dbAlgorithmsType = ShardingConfigEnums.ShardingAlgorithmType.CLASS_BASED,
        dbStrategy = ShardingConfigEnums.ShardingStrategy.STANDARD,
        dbAlgorithmClassName = "com.base.strategy.StandardDbPreciseStandardShardingAlgorithm",
        dbExpression = "sharding_key%4",
        tbShardingCount = 4
)
@TableName("sequence")

Шаг 2: Реализация сканера, который будет просматривать классы в пакете и искать аннотации, как показано ниже: PackageScanner.java

    // Поиск классов, аннотированных аннотацией @TableName
    Set<Class<?>> annotatedClassesInPackage = PackageScanner.getAnnotatedClassesInPackages(packages, TableName.class);

Шаг 3: Реализация SPI: CustomClassPathURLLoader.java, при получении конфигурации, анализировать найденные классы, создавать конфигурационные файлы, как показано ниже: Определение: конфигурация custmer-classpath и определение переменной: useAutoConfig, указывающей, использовать ли автоматическую конфигурацию аннотаций````java /**

  • @title: CustomClassPathURLLoader

  • @description: Реализация SPI, чтение конфигурации, автоматическое создание конфигурационных файлов

  • @author: arron

  • @date: 2024/8/28 22:09 */ @Slf4j public class CustomClassPathURLLoader implements ShardingSphereURLLoader {

    /**

    • Определение типа jdbc:shardingsphere: после customer-classpath: */ private static final String CUSTOMER_CLASSPATH_TYPE = "customer-classpath:";

    /**

    • Принимает customer:classpath:
    • @param configurationSubject идентификатор конфигурации dataId
    • @param queryProps параметры URL, уже распаршенные в Properties
    • @return */ @Override @SneakyThrows public String load(String configurationSubject, Properties queryProps) { try (InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(configurationSubject)) { Objects.requireNonNull(inputStream); try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) { String config = reader.lines().collect(Collectors.joining(System.lineSeparator())); String useAutoConfig = queryProps.getProperty("useAutoConfig"); if (!StringUtils.isBlank(useAutoConfig) && Boolean.parseBoolean(useAutoConfig)) { config = ShardingRuleScanAndGenerate.generateConfig(config); } log.warn("Автоматически сгенерированная конфигурация для распределения таблиц:\n{}", config); return config; } } }

    @Override public Object getType() { return CUSTOMER_CLASSPATH_TYPE; } }


[application.yaml](local-mode-5.5.0%2Fsrc%2Fmain%2Fresources%2Fapplication.yaml)
````yaml 
spring:
  datasource:
    url: jdbc:shardingsphere:customer-classpath:sharding.yaml?useAutoConfig=true
````[sharding.yaml](local-mode-5.5.0%2Fsrc%2Fmain%2Fresources%2Fsharding.yaml) Необходимо только конфигурировать информацию о данных источниках, остальные конфигурации будут заданы пользовательскими аннотациями, как показано ниже:Обратите внимание, что необходимо выполнить сканирование для классов, которые требуются для распределения по базам данных и таблицам: scan-package: com.base.domain,com.base.entity

````yaml
dataSources:
  ds_0:
    driverClassName: com.mysql.cj.jdbc.Driver
    dataSourceClassName: com.zaxxer.hikari.HikariDataSource
    url: jdbc:mysql://localhost:3306/db_sequence_0?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
    username: root
    password: root
  ds_1:
    driverClassName: com.mysql.cj.jdbc.Driver
    dataSourceClassName: com.zaxxer.hikari.HikariDataSource
    url: jdbc:mysql://localhost:3306/db_sequence_1?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
    username: root
    password: root
props:
  sql-show: true
  # Сканируемые пакеты, автоматически сгенерированные для распределения по базам данных и таблицам, несколько пакетов разделены запятой или точкой с запятой
  scan-package: com.base.domain,com.base.entity

Шаг 4: Реализация класса для сборки конфигурации: ShardingRuleScanAndGenerate.java, с использованием конфигураций, полученных из аннотаций, для сборки конфигурации, и возвращения конфигурации через SPI:

``````markdown
/**
 * @title: ShardingRuleScanAndGenerate
 * @description: При запуске сканирует и генерирует правила
 * @author: arron
 * @date: 2024/9/1 11:50
 */
@Slf4j
public class ShardingRuleScanAndGenerate {    /**
     * Использует конфигурацию для генерации конфигурации
     * @param config
     * @return
     */
    public static String generateConfig(String config) {
        Yaml yaml = new Yaml();
        Map<String, JSONObject> parsedData = yaml.load(config);
        Map<String, JSONObject> dataSources = (LinkedHashMap) parsedData.get("dataSources");
        if (dataSources == null) {
            log.error("нет конфигурации dataSources");
            throw new RuntimeException("нет конфигурации dataSources");
        }
        Map<String, JSONObject> scanPackages = (LinkedHashMap) parsedData.get("props");
        if (scanPackages == null){
            log.error("нет конфигурации scan-пакета");
            throw new RuntimeException("нет конфигурации scan-пакета");
        }
        String packages = scanPackages.get("scan-package");
        if (StringUtils.isBlank(packages)){
            log.error("нет конфигурации scan-пакета");
            throw new RuntimeException("нет конфигурации scan-пакета");
        }
        config = config + generateConfig(dataSources, packages);
        return config;
    }```java
    public static String generateConfig(Map<String, JSONObject> dataSources, String packages) {
        Set<Class<?>> annotatedClassesInPackage = PackageScanner.getAnnotatedClassesInPackages(packages, TableName.class);
        log.info("Обнаружены классы с распределенными таблицами: {}", JSONObject.toJSONString(annotatedClassesInPackage));
        String space2 = "  ";

        StringBuffer sb = new StringBuffer();
        sb.append("\n");
        sb.append("rules:").append("\n");
        sb.append(space2).append("- !SHARDING").append("\n");
        sb.append(space2).append(space2).append("tables:").append("\n");

        //TODO Генерация правил распределения
        for (Class<?> clazz : annotatedClassesInPackage) {
            TableName tableName = clazz.getAnnotation(TableName.class);
            if (tableName == null) {
                continue;
            }
            // Имя таблицы
            String tb_name = tableName.value();
            sb.append(space2).append(space2).append(space2).append(tb_name).append(":\n");

            ShardingConfig shardingConfig = clazz.getAnnotation(ShardingConfig.class);
            if (shardingConfig == null) {
                continue;
            }
        }
    }
}
```            
```java
            int tbShardingCount = shardingConfig.tbShardingCount();
            String actualDataNodes = getActualDataNodes(tb_name, dataSources, tbShardingCount);
            sb.append(space2).append(space2).append(space2).append(space2).append(actualDataNodes).append("\n");

            // Стратегия распределения по базам данных
            sb.append(space2).append(space2).append(space2).append(space2).append("databaseStrategy").append(":\n");

            // Поля для распределения
            String shardingColumn = shardingConfig.shardingColumn();

            // Алгоритм распределения по базам данных
            String dbStrategy = shardingConfig.dbStrategy().name();

            // Алгоритм распределения по таблицам
            String tbStrategy = shardingConfig.tbStrategy().name();
```            sb.append(space2).append(space2).append(space2).append(space2).append(space2).append(dbStrategy.toLowerCase()).append(":\n");
            //TODO Определить, является ли это составным полем
            if (ShardingConfigEnums.ShardingStrategy.STANDARD.equals(shardingConfig.dbStrategy())) {
                sb.append(space2).append(space2).append(space2).append(space2).append(space2).append(space2).append("shardingColumn: ").append(shardingColumn).append("\n");
            } else {
                sb.append(space2).append(space2).append(space2).append(space2).append(space2).append(space2).append("shardingColumns: ").append(shardingColumn).append("\n");
            }
            String default_db_strategy = "default_db_" + tb_name + "_strategy";
            sb.append(space2).append(space2).append(space2).append(space2).append(space2).append(space2).append("shardingAlgorithmName: ").append(default_db_strategy).append("\n");

            //TODO Определить, является ли это составным полем
            if (ShardingConfigEnums.ShardingStrategy.STANDARD.equals(shardingConfig.dbStrategy())) {
                sb.append(space2).append(space2).append(space2).append(space2).append(space2).append(space2).append("shardingColumn: ").append(shardingColumn).append("\n");
            } else {
                sb.append(space2).append(space2).append(space2).append(space2).append(space2).append(space2).append("shardingColumns: ").append(shardingColumn).append("\n");
            }
            String default_db_strategy = "default_db_" + tb_name + "_strategy";
            sb.append(space2).append(space2).append(space2).append(space2).append(space2).append(space2).append("shardingAlgorithmName: ").append(default_db_strategy).append("\n");

            //TODO Определить, является ли это составным полем
            if (ShardingConfigEnums.ShardingStrategy.STANDARD.equals(shardingConfig.dbStrategy())) {
                sb.append(space2).append(space2).append(space2).append(space2).append(space2).append(space2).append("shardingColumn: ").append(shardingColumn).append("\n");
            } else {
                sb.append(space2).append(space2).append(space2).append(space2).append(space2).append(space2).append("shardingColumns: ").append(shardingColumn).append("\n");
            }
            String default_db_strategy = "default_db_" + tb_name + "_strategy";
            sb.append(space2).append(space2).append(space2).append(space2).append(space2).append(space2).append("shardingAlgorithmName: ").append(default_db_strategy).append("\n");

            //TODO Определить, является ли это составным полем
            if (ShardingConfigEnums.ShardingStrategy.STANDARD.equals(shardingConfig.dbStrategy())) {
                sb.append(space2).append(space2).append(space2).append(space2).append(space2).append(space2).append("shardingColumn: ").append(shardingColumn).append("\n");
            } else {
                sb.append(space2).append(space2).append(space2).append(space2).append(space2).append(space2).append("shardingColumns: ").append(shardingColumn).append("\n");
            }
            String default_db_strategy = "default_db_" + tb_name + "_strategy";
            sb.append(space2).append(space2).append(space2).append(space2).append(space2).append(space2).append("shardingAlgorithmName: ").append(default_db_strategy).append("\n");

            //TODO Определить, является ли это составным полем
            if (ShardingConfigEnums.ShardingStrategy.STANDARD.equals(shardingConfig.dbStrategy())) {
                sb.append(space2).append(space2).append(space2).append(space2).append(space2).append(space2).append("shardingColumn: ").append(shardingColumn).append("\n");
            } else {
                sb.append(space2).append(space2).append(space2).append(space2).append(space2).append(space2).append("shardingColumns: ").append(shardingColumn).append("\n");
            }
            String default_db_strategy = "default_db_" + tb_name + "_strategy";
            sb.append(space2).append(space2).append(space2).append(space2).append(space2).append(space2).append("shardingAlgorithmName: ").append(default_db_strategy).append("\n");

            //TODO Определить, является ли это составным полем
            if (ShardingConfigEnums.ShardingStrategy.STANDARD.equals(shardingConfig.dbStrategy())) {
                sb.append(space2).append(space2).append(space2).append(space2).append(space2).append(space2).append("shardingColumn: ").append(shardingColumn).append("\n");
            } else {
                sb.append(space2).append(space2).append(space2).append(space2).append(space2).append(space2).append("shardingColumns: ").append(shardingColumn).append("\n");
            }
            String default_db_strategy = "default_db_" + tb_name + "_strategy";
            sb.append(space2).append(space2).append(space2).append(space2).append(space2).append(space2).append("shardingAlgorithmName: ").append(default_db_strategy).append("\n");

            //TODO Определить, является ли это составным полем
            if (ShardingConfigEnums.ShardingStrategy.STANDARD.equals(shardingConfig.dbStrategy())) {
                sb.append(space2).append(space2).append(space2).append(space2).append(space2).append(space2).append("shardingColumn: ").append(shardingColumn).append("\n");
            } else {
                sb.append(space2).append(space2).append(space2).append(space2).append(space2).append(space2).append("shardingColumns: ").append(shardingColumn).append("\n");
            }
            String default_db_strategy = "default_db_" + tb_name + "_strategy";
            sb.append(space2).append(space2).append(space2).append(space2).append(space2).append(space2).append("shardingAlgorithmName: ").append(default_db_strategy).append("\n");

            //TODO Определить, является ли это составным полем
            if (ShardingConfigEnums.ShardingStrategy.STANDARD.equals(shardingConfig.dbStrategy())) {
                sb.append(space2).append(space2).append(space2).append(space2).append(space2).append(space2).append("shardingColumn: ").append(shardingColumn).append("\n");
            } else {
                sb.append(space2).append(space2).append(space2).append(space2).append(space2).append(space2).append("shardingColumns: ").append(shardingColumn).append("\n");
            }
            String default_db_strategy = "default_db_" + tb_name + "_strategy";
            sb.append(space2).append(space2).append(space2).append(space2).append(space2).append(space2).append("shardingAlgorithmName: ").append(default_db_strategy).append("\n");

            //TODO Определить, является ли это составным полем
            if (ShardingConfigEnums.ShardingStrategy.STANDARD.equals(shardingConfig.dbStrategy())) {
                sb.append(space2).append(space2).append(space2).append(space2).append(space2).append(space2).append("shardingColumn: ").append(shardingColumn).append("\n");
            } else {
                sb.append(space2).append(space2).append(space2).append(space2).append(space2).append(space2).append("shardingColumns: ").append(shardingColumn).append("\n");
            }
            String default_db_strategy = "default_db_" + tb_name + "_strategy";
            sb.append(space2).append(space2).append(space2).append(space2).append(space2).append(space2).append("shardingAlgorithmName: ").append(default_db_strategy).append("\n");

            //TODO Определить, является ли это составным полем
            if (ShardingConfigEnums.ShardingStrategy.STANDARD.equals(shardingConfig.dbStrategy())) {
                sb.append(space2).append(space2).append(space2).append(space2).append(space2).append(space2).append("shardingColumn: ").append(shardingColumn).append("\n");
            } else {
                sb.append(space2).append(space2).append(space2).append(space2).append(space2).append(space2).append("shardingColumns: ").append(shardingColumn).append("\n");
            }
            String default_db_strategy = "default_db_" + tb_name + "_strategy";
            sb.append(space2).append(space2).append(space2).append(space2).append(space2).append(space2).append("shardingAlgorithmName: ").append(default_db_strategy).append("\n");

            //TODO Определить, является ли это составным полем
            if (ShardingConfigEnums.ShardingStrategy.STANDARD.equals(shardingConfig.dbStrategy())) {
                sb.append(space2).append(space2).append(space2).append(space2).append(space2).append(space2).append("shardingColumn: ").append(shardingColumn).append("\n");
            } else {
                sb.append(space2).append(space2).append(space2).append(space2).append(space2).append(space2).append("shardingColumns: ").append(shardingColumn).append("\n");
            }
            String default_db_strategy = "default_db_" + tb_name + "_strategy";
            sb.append(space2).append(space2).append(space2).append(space2).append(space2).append(space2).append("shardingAlgorithmName: ").append(default_db_strategy).append("\n");

            //TODO Определить, является ли это составным полем
            if (ShardingConfigEnums.ShardingStrategy.STANDARD.equals(shardingConfig.dbStrategy())) {
                sb.append(space2).append(space2).append(space2).append(space2).append(space2).append(space2).append("shardingColumn: ").append(shardingColumn).append("\n");
            } else {
                sb.append(space2).append(space2).append(space2).append(space2).append(space2).append(space2).append("shardingColumns: ").append(shardingColumn).append("\n");
            }
            String default_db_strategy = "default_db_" + tb_name + "_strategy";
            sb.append(space2).append(space2).append(space2).append(space2).append(space2).append(space2).append("shardingAlgorithmName: ").append(default_db_strategy).append("\n");

            //TODO Определить, является ли это составным полем
            if (ShardingConfigEnums.ShardingStrategy.STANDARD.equals(shardingConfig.dbStrategy())) {
                sb.append(space2).append(space2).append(space2).append(space2).append(space2).append(space2).append("shardingColumn: ").append(shardingColumn).append("\n");
            } else {
                sb.append(space2).append(space2).append(space2).append(space2).append(space2).append(space2).append("shardingColumns: ").append(shardingColumn).append("\n");
            }
            String default_db_strategy = "default_db_" + tb_name + "_strategy";
            sb.append(space2).append(space2).append(space2).append(space2).append(space2).append(space2).append("shardingAlgorithmName: ").append(default_db_strategy).append("\n");

            //TODO Определить, является ли это составным полем
            if (ShardingConfigEnums.ShardingStrategy.STANDARD.equals(shardingConfig.dbStrategy())) {
                sb.append(space2).append(space2).append(space2).append(space2).append(space2).append(space2).append("            // Стратегия распределения по таблицам
            sb.append(space2).append(space2).append(space2).append(space2).append("tableStrategy").append(":\n");
            sb.append(space2).append(space2).append(space2).append(space2).append(space2).append(tbStrategy.toLowerCase()).append(":\n");            //TODO Проверить, является ли это составным ключом
            if (ShardingConfigEnums.ShardingStrategy.STANDARD.equals(shardingConfig.tbStrategy())) {
                sb.append(space2).append(space2).append(space2).append(space2).append(space2).append(space2).append("shardingColumn: ").append(shardingColumn).append("\n");
            } else {
                sb.append(space2).append(space2).append(space2).append(space2).append(space2).append(space2).append("shardingColumns: ").append(shardingColumn).append("\n");
            }
            String default_tb_strategy = "default_tb_" + tb_name + "_strategy";
            sb.append(space2).append(space2).append(space2).append(space2).append(space2).append(space2).append("shardingAlgorithmName: ").append(default_tb_strategy).append("\n");
        }        String шардингАлгоритмы = "шардингАлгоритмы:";
        sb.append(пробел2).append(пробел2).append(шардингАлгоритмы).append("\n");

        //TODO Определение шардинг алгоритмов
        for (Class<?> clazz : аннотированныеКлассыВПакете) {
            TableName tableName = clazz.getAnnotation(TableName.class);
            if (tableName == null) {
                continue;
            }
            // Имя таблицы
            String tb_name = tableName.value();

            ShardingConfig шардингКонфиг = clazz.getAnnotation(ShardingConfig.class);
            if (шардингКонфиг == null) {
                continue;
            }
            // Алгоритм шардинга для баз данных
            String dbAlgorithmType = шардингКонфиг.dbAlgorithmsType().name();
            String dbAlgorithmClassName = шардингКонфиг.dbAlgorithmClassName();
            String dbStrategy = шардингКонфиг.dbStrategy().name();
            String dbExpression = шардингКонфиг.dbExpression();
            String шардингАлгоритмы = "шардингАлгоритмы:";
            sb.append(пробел2).append(пробел2).append(шардингАлгоритмы).append("\n");            // Алгоритм шардинга для таблиц
            String tbAlgorithmType = шардингКонфиг.tbAlgorithmsType().name();
            String tbAlgorithmClassName = шардингКонфиг.tbAlgorithmClassName();
            String tbExpression = шардингКонфиг.tbExpression();
            String tbStrategy = шардингКонфиг.tbStrategy().name();

            String default_db_strategy = "default_db_" + tb_name + "_strategy";
            // Шардинг для баз данных
            sb.append(пробел2).append(пробел2).append(пробел2).append(default_db_strategy).append(":\n");
            sb.append(пробел2).append(пробел2).append(пробел2).append(пробел2).append("type: ").append(dbAlgorithmType).append("\n");
            sb.append(пробел2).append(пробел2).append(пробел2).append(пробел2).append("props:").append("\n");
            sb.append(пробел2).append(пробел2).append(пробел2).append(пробел2).append(пробел2).append("strategy: ").append(dbStrategy).append("\n");
            sb.append(пробел2).append(пробел2).append(пробел2).append(пробел2).append(пробел2).append("algorithmClassName: ").append(dbAlgorithmClassName).append("\n");
            sb.append(пробел2).append(пробел2).append(пробел2).append(пробел2).append(пробел2).append("expression: ").append(dbExpression).append("\n");

```markdown
String default_tb_strategy = "default_tb_" + tb_name + "_strategy";
# Шарды
sb.append(space2).append(space2).append(space2).append(default_tb_strategy).append(":\n");
sb.append(space2).append(space2).append(space2).append(space2).append("type: ").append(tbAlgorithmType).append("\n");
sb.append(space2).append(space2).append(space2).append(space2).append("props:").append("\n");
sb.append(space2).append(space2).append(space2).append(space2).append(space2).append("strategy: ").append(tbStrategy).append("\n");
sb.append(space2).append(space2).append(space2).append(space2).append(space2).append("algorithmClassName: ").append(tbAlgorithmClassName).append("\n");
sb.append(space2).append(space2).append(space2).append(space2).append(space2).append("expression: ").append(tbExpression).append("\n");
```Текст переведён на русский язык, сохраняя структуру и форматирование исходного текста.

```java
String tableConfig = sb.toString();
//        log.warn("Автоматически сгенерированное конфигурационное распределение по таблицам:\n{}", tableConfig);
        return tableConfig;
    }

    public static String getActualDataNodes(String tbName, Map<String, JSONObject> dataSources, int tbShardingCount) {
        // Количество баз данных
        Set<String> dbKeySet = dataSources.keySet();
        int dbSize = dbKeySet.size();
        String actualDataNodes = "actualDataNodes:";

        if (dbSize == 1) {
            String dbName = dbKeySet.iterator().next();
            actualDataNodes = actualDataNodes + " " + dbName + "." + tbName;
            return actualDataNodes;
        }

        int i = 0;
        for (String key : dbKeySet) {
            String dbName = key;
            actualDataNodes = actualDataNodes + " " + dbName + "." + tbName + "_${0.." + (tbShardingCount - 1) + "}";
            if (i < dbSize - 1) {
                actualDataNodes = actualDataNodes + ",";
            }
            i++;
        }
        return actualDataNodes;
    }
}

Тест

img.png

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/dragonyeah-shardingsphere-5.5.0-example.git
git@api.gitlife.ru:oschina-mirror/dragonyeah-shardingsphere-5.5.0-example.git
oschina-mirror
dragonyeah-shardingsphere-5.5.0-example
dragonyeah-shardingsphere-5.5.0-example
main