mybatis-plus 動態數據源 clickHouse集群


背景:

當前項目使用的 mybatis-plus 多數據源框架,使用方式可參考:

https://mp.baomidou.com/guide/dynamic-datasource.html#文檔-documentation

默認多數據源配置,並不支持clickHouse 多節點信息,可通過如下方式擴展:

pom.xml

...

<mybatis.plus.version>3.4.3.4</mybatis.plus.version>
<dynamic.datasource.version>3.4.1</dynamic.datasource.version>
<clickhouse.version>0.3.1-patch</clickhouse.version>

...
<dependency>
   <groupId>ru.yandex.clickhouse</groupId>
   <artifactId>clickhouse-jdbc</artifactId>
   <version>${clickhouse.version}</version>
</dependency>
<dependency>
  <groupId>com.baomidou</groupId>
  <artifactId>mybatis-plus-boot-starter</artifactId>
  <version>${mybatis.plus.version}</version>
</dependency>
<dependency>
  <groupId>com.baomidou</groupId>
  <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
  <version>${dynamic.datasource.version}</version>
</dependency>

Java代碼:

增加自定義的動態數據源配置

// 保證執行順序在前面,否則 會被其他加載器給創建,導致自定義的加載器執行不到
@Order(0)
@Configuration
public class DynamicDataSourceConfig extends AbstractDataSourceCreator implements DataSourceCreator {
    protected DynamicDataSourceConfig(DynamicDataSourceProperties dynamicDataSourceProperties) {
        super(dynamicDataSourceProperties);
    }

    @Override
    public DataSource doCreateDataSource(DataSourceProperty dataSourceProperty) {
        // 如果需要其他參數,自行加入,可以在配置文件配置,此處從dataSourceProperty獲取,並填充
        Properties properties = new Properties();
        // 使用clickHouse
        return new BalancedClickhouseDataSource(dataSourceProperty.getUrl(), properties);
    }

    @Override
    public boolean support(DataSourceProperty dataSourceProperty) {
        // 適配器模式,判斷是否需要使用當前動態數據源創建
        Class<? extends DataSource> type = dataSourceProperty.getType();
        if (Objects.isNull(type)) {
            return Boolean.FALSE;
        }
        return StringUtils.equals(type.getName(), BalancedClickhouseDataSource.class.getName());
    }
}

使用方式

// 標注此 mapper 查詢使用 clickHouse 數據源,和 配置文件中名稱對應
@DS("clickHouse")
public interface TestMapper extends BaseMapper<TestEntity> {

}

application.yaml

spring:
  datasource:
    dynamic:
      primary: master #指定默認數據源
      strict: true
      datasource:
        master:
          driver-class-name: com.mysql.cj.jdbc.Driver
          url: jdbc:mysql://xxxx:3306/xxx?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&zeroDateTimeBehavior=convertToNull
          username: xx
          password: xx
          hikari:
            minimum-idle: 5
            idle-timeout: 600000
            maximum-pool-size: 20
            max-lifetime: 1800000
            connection-timeout: 6000
            connection-test-query: SELECT 1
        clickHouse:
          # 此處type 主要用作 java代碼中適配器的判斷
          type: ru.yandex.clickhouse.BalancedClickhouseDataSource
          driver-class-name: ru.yandex.clickhouse.ClickHouseDriver
          # jdbc:clickhouse://ip:port,ip:port/xxx 配置格式
          url: jdbc:clickhouse://xxxx:8123,xxxx:8123/xxx

原理解析

BalancedClickhouseDataSource.class

此數據源為clickHousejdbc提供的集群DataSource

所以我們要做的就是使用此數據源來創建DataSource


    /**
     * create Datasource for clickhouse JDBC connections
     *
     * @param url address for connection to the database
     *            must have the next format {@code jdbc:clickhouse://<first-host>:<port>,<second-host>:<port>/<database>?param1=value1&param2=value2 }
     *            for example, {@code jdbc:clickhouse://localhost:8123,localhost:8123/database?compress=1&decompress=2 }
     * @throws IllegalArgumentException if param have not correct format, or error happens when checking host availability
     */
    public BalancedClickhouseDataSource(final String url) {
        this(splitUrl(url), getFromUrl(url));
    }

com.baomidou.dynamic.datasource.creator.DefaultDataSourceCreator

源碼中,通過此類來初始化配置文件中的 數據源

@Slf4j
@Setter
public class DefaultDataSourceCreator {
	  // 默認的實現類中,BasicDataSourceCreator 的 support方法始終為true,所以自定義的動態數據源配置,必須在 BasicDataSourceCreator 之前執行,需要設置 @Order
    private List<DataSourceCreator> creators;

    public DataSource createDataSource(DataSourceProperty dataSourceProperty) {
        DataSourceCreator dataSourceCreator = null;
        for (DataSourceCreator creator : this.creators) {
            // 適配器判斷,是否使用此數據源
            if (creator.support(dataSourceProperty)) {
                dataSourceCreator = creator;
                break;
            }
        }
        if (dataSourceCreator == null) {
            throw new IllegalStateException("creator must not be null,please check the DataSourceCreator");
        }
        // 創建數據源
        return dataSourceCreator.createDataSource(dataSourceProperty);
    }

}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM