1. 程式人生 > 實用技巧 >SpringBoot整合ShardingSphere 4.x單庫 分表

SpringBoot整合ShardingSphere 4.x單庫 分表

1,pom.xml

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

2,yml

spring:
  shardingsphere:
    datasource:
      names: db0 # 資料來源名稱
      db0:
        driver
-class-name: com.mysql.jdbc.Driver jdbc-url: jdbc:mysql://xxxxxx:3306/zjk_coal?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false username: ENC(8r6fF8d+ujG2HXBDoBq3wg==) password: ENC(ms9QKba7NE/DtPNukwrykQ==) type: com.zaxxer.hikari.HikariDataSource hikari: minimum
-idle: 5 maximum-pool-size: 15 auto-commit: true idle-timeout: 30000 pool-name: DatebookHikariCP max-lifetime: 1800000 connection-timeout: 30000 connection-test-query: SELECT 1 sharding: tables: alarm_equipment: # 表名 actual
-data-nodes: db0.alarm_equipment_202009, db0.alarm_equipment_202010, db0.alarm_equipment_202011, db0.alarm_equipment_202011, db0.alarm_equipment_$->{2021..2022}0$->{1..9}, db0.alarm_equipment_$->{2021..2022}$->{10..12} table-strategy: # inline: # sharding-column: id # 分片鍵 # algorithm-expression: alarm_equipment$->{id % 3} standard: sharding-column: date_time # 分片鍵 precise-algorithm-class-name: com.chitic.zjkcte.common.common.config.sharding.TableShardingAlgorithm # 實現類的完全限定類名 range-algorithm-class-name: com.chitic.zjkcte.common.common.config.sharding.TableRangeShardingAlgorithm # 列印SQL,不配置 列印的都是邏輯表 props: sql: show: true
  jpa:
hibernate:
# 生產環境設定成 none,避免程式執行時自動更新資料庫結構
ddl-auto: none
show-sql: false


3,標準分片策略

精確的分片演算法類名稱,用於=和IN
package com.chitic.zjkcte.common.common.config.sharding;

import com.chitic.module.core.exception.ChiticException;
import com.chitic.zjkcte.common.common.enums.ResponseCode;
import com.chitic.zjkcte.common.common.util.BaseDateUtils;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingValue;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Collection;
import java.util.Date;

/**
 * @Description //TODO 標準分片策略  精確的分片演算法類名稱,用於=和IN
 * @Author GaoX
 * @Date 2020/11/18 15:56
 */
@Component
public class TableShardingAlgorithm implements PreciseShardingAlgorithm {

    @Override
    public String doSharding(Collection availableTargetNames, PreciseShardingValue preciseShardingValue) {
        // 基本的表名_年份月份  base_202011
        //TODO 此處接收是Integer  不明白為什麼
        Object value = preciseShardingValue.getValue();
        final String format = "yyyyMM";
        String targetTable = preciseShardingValue.getLogicTableName() + "_" + BaseDateUtils.getFormatDate(Long.parseLong(value.toString()), format);
        if (availableTargetNames.contains(targetTable)){
            return targetTable;
        }
        throw ChiticException.of(ResponseCode.SYSTEM_ERROR.getCode(), "無效的表名稱: " + targetTable);
    }
}
標準分片策略 範圍的分片演算法類名稱,用於BETWEEN
package com.chitic.zjkcte.common.common.config.sharding;

import com.chitic.module.core.exception.ChiticException;
import com.chitic.zjkcte.common.common.enums.ResponseCode;
import com.chitic.zjkcte.common.common.util.BaseDateUtils;
import com.google.common.collect.Range;
import org.apache.shardingsphere.api.sharding.standard.RangeShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.RangeShardingValue;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.Collection;
/**
 * @Description //TODO 標準分片策略 範圍的分片演算法類名稱,用於BETWEEN
 * @Author GaoX
 * @Date 2020/11/18 16:06
 */
@Component
public class TableRangeShardingAlgorithm implements RangeShardingAlgorithm<Integer> {

    @Override
    public Collection<String> doSharding(Collection<String> collection, RangeShardingValue<Integer> rangeShardingValue) {
        Collection<String> collect = new ArrayList<>();
        Range valueRange = rangeShardingValue.getValueRange();
        //TODO 這種寫法只支援between, 但是效率很高
        //Comparable lowerEndpoint = valueRange.lowerEndpoint();
        //Comparable upperEndpoint = valueRange.upperEndpoint();
        //String lowerEndTable = rangeShardingValue.getLogicTableName() + "_" + BaseDateUtils.getFormatDate(Long.parseLong(lowerEndpoint.toString()), "yyyyMM");
        //String upperEndTable = rangeShardingValue.getLogicTableName() + "_" + BaseDateUtils.getFormatDate(Long.parseLong(upperEndpoint.toString()), "yyyyMM");
        for (String each : collection) {
            Integer shardValue = Integer.parseInt(each.substring(each.lastIndexOf("_") + 1, each.lastIndexOf("_") + 7));
            if (valueRange.hasLowerBound()) {
                String lowerStr = valueRange.lowerEndpoint().toString();
                String date = BaseDateUtils.getFormatDate(Long.parseLong(lowerStr), "yyyyMM");
                Integer start = Integer.parseInt(date);
                if (start - shardValue > 0) {
                    continue;
                }
            }
            if (valueRange.hasUpperBound()) {
                String upperStr = valueRange.upperEndpoint().toString();
                String date = BaseDateUtils.getFormatDate(Long.parseLong(upperStr), "yyyyMM");
                Integer end = Integer.parseInt(date);
                if (end - shardValue < 0) {
                    continue;
                }
            }
            collect.add(each);
        }
        if(CollectionUtils.isEmpty(collect)){
            throw ChiticException.of(ResponseCode.SYSTEM_ERROR.getCode(), "無效的表" );
        }
        return collect;
    }


}

4,資料庫表

5,entity和dao

實體類正常寫就好,@Table ( name ="alarm_equipment" ) 是邏輯表名