0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Spring Boot + MyBatisでマルチデータソースで同一のMapperクラスを使用する方法

Last updated at Posted at 2020-04-22

はじめに

私が経験した案件において、
異なるデータソース、同一テーブル定義を用いたシステムを構築したので、
そのときのノウハウを共有します。

データソース定義

ドライバは「Oracle」を使用していますが、環境に合わせて適宜修正してください。

application.yml
spring:
  datasource:
    # データソースA
    alpha:
      jdbc-url: jdbc:oracle:thin:@localhost:1521/XEPDB1
      username: sample_a
      password: sample_a
      driverClassName: oracle.jdbc.OracleDriver
    # データソースB
    beta:
      jdbc-url: jdbc:oracle:thin:@localhost:1521/XEPDB1
      username: sample_b
      password: sample_b
      driverClassName: oracle.jdbc.OracleDriver

MyBatisの設定

DataSourceConfig.java
package com.example;

@Configuration
@MapperScan(basePackages = { "com.example.mapper" }, sqlSessionTemplateRef = "sqlSessionTemplate") // ①
public class DataSourceConfig {

    @Bean(name = "alphaDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.alpha")
    public DataSource alphaDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "betaDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.beta")
    public DataSource betaDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean("dynamicDataSource")
    public DynamicRoutingDataSourceResolver dynamicDataSource(@Qualifier("alphaDataSource") DataSource alphaDataSource, @Qualifier("betaDataSource") DataSource betaDataSource) {
        Map<Object, Object> targetDataSources = new HashMap<Object, Object>();
        targetDataSources.put(DataSourceType.ALPHA, alphaDataSource);
        targetDataSources.put(DataSourceType.BETA, betaDataSource);

        // データソースの動的変更
        DynamicRoutingDataSourceResolver resolver = new DynamicRoutingDataSourceResolver();
        resolver.setTargetDataSources(targetDataSources);
        resolver.setDefaultTargetDataSource(alphaDataSource);

        return resolver;
    }

    @Bean
    public SqlSessionFactory sqlSessionFactory(@Qualifier("dynamicDataSource") DynamicRoutingDataSourceResolver resolver) throws Exception {
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();

        // ②
        factoryBean.setDataSource(resolver);
        factoryBean.setMapperLocations("Mapper XMLのパス");
        factoryBean.getObject().getConfiguration().setMapUnderscoreToCamelCase(true);

        return factoryBean.getObject();
    }

    // ... 省略
}

①: 共通使用するMapperクラスのエイリアスを設定する
②: マルチデータソースではAutoConfigureが無効になるため、手動で設定する
公式サイトに記載があります

データソース切替

参照データソースを判断するための区分値を定義する。

public enum DataSourceType {
    ALPHA, BETA
}

スレッド単位で区分値を保持する。

DataSourceContextHolder.java
public class DataSourceContextHolder {

    private static ThreadLocal<DataSourceType> contextHolder = new ThreadLocal<DataSourceType>();

    public static void setDataSourceType(DataSourceType dataSourceType) {
        contextHolder.set(dataSourceType);
    }

    public static DataSourceType getDataSourceType() {
        return contextHolder.get();
    }

    public static void clear() {
        contextHolder.remove();
    }
}

参照データソース判断用の区分値を取得する。
この区分値でDataSourceConfig.dynamicDataSourceで設定されたデータソースから、
実際に参照するデータソースを判断する。

DynamicRoutingDataSourceResolver.java
public class DynamicRoutingDataSourceResolver extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceContextHolder.getDataSourceType();
    }
}

使用方法

DataSourceContextHolder経由で、DataSourceTypeを設定しましょう。
横断処理として定義したい場合は、AOPなどを使用してデータソース切替を行ってください。

DataSourceContextHolder.setDataSourceType(DataSourceType.ALPHA);
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?