Mybatisで使用するデータソースを切り替える方法

Mybatisで使用するデータソースを切り替える方法

MyBatisで使用するデータソースを切り替える方法

MyBatisで複数のデータソースを使用する場合、環境や処理内容に応じて適切なデータソースに切り替える必要があります。
以下では、データソースの切り替え方法について説明します。

データソースの設定

まず、DataSourceを複数設定します。
例えば、testDataSource1とtestDataSource2の2つのデータソースを用意する場合の設定は次のようになります。
application.propertiesやapplication.ymlにデータソースの設定を追加します。

application.properties(プロパティファイルでの設定例)

# testDataSource1の設定
spring.datasource.testDataSource1.url=jdbc:mysql://localhost:3306/testdb1
spring.datasource.testDataSource1.username=root
spring.datasource.testDataSource1.password=password1

# testDataSource2の設定
spring.datasource.testDataSource2.url=jdbc:mysql://localhost:3306/testdb2
spring.datasource.testDataSource2.username=root
spring.datasource.testDataSource2.password=password2

application.yml(YAMLファイルでの設定例)

spring:
  datasource:
    testDataSource1:
      url: jdbc:mysql://localhost:3306/testdb1
      username: root
      password: password1

    testDataSource2:
      url: jdbc:mysql://localhost:3306/testdb2
      username: root
      password: password2

データソースの切り替え

データソースを切り替えるには、DataSourceを管理するコンポーネントを作成し、動的にデータソースを切り替えるロジックを実装します。
以下にその一例を示します。

DataSourceConfig.java

import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import org.springframework.jdbc.datasource.lookup.DataSourceLookupFailureException;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

@Configuration
public class DataSourceConfig {

    @Bean
    public DataSource dataSource() {
        AbstractRoutingDataSource routingDataSource = new AbstractRoutingDataSource() {
            @Override
            protected Object determineCurrentLookupKey() {
                return DataSourceContextHolder.getDataSourceType();
            }
        };

        Map<Object, Object> dataSourceMap = new HashMap<>();
        dataSourceMap.put("testDataSource1", testDataSource1());
        dataSourceMap.put("testDataSource2", testDataSource2());

        routingDataSource.setTargetDataSources(dataSourceMap);
        return routingDataSource;
    }

    @Bean
    public DataSource testDataSource1() {
        // testDataSource1の設定
    }

    @Bean
    public DataSource testDataSource2() {
        // testDataSource2の設定
    }

    @Bean
    public DataSourceTransactionManager transactionManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource);
        return sessionFactory.getObject();
    }
}

DataSourceContextHolder.java

public class DataSourceContextHolder {
    private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();

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

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

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

データソースの切り替えの使用

サービスやリポジトリでデータソースを切り替える際には、DataSourceContextHolderを使用して適切なデータソースを設定します。

UserService.java

@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;

    public void performOperation(String dataSourceType) {
        DataSourceContextHolder.setDataSourceType(dataSourceType);
        // ビジネスロジックやデータ操作を行う
        userMapper.getUsers();
        DataSourceContextHolder.clearDataSourceType();
    }
}

このように、DataSourceContextHolderを用いて、データソースを動的に切り替えることができます。
切り替えが必要な操作が完了したら、必ずDataSourceContextHolder.clearDataSourceType()を呼び出し、スレッドローカルのデータソースタイプをクリアすることが重要です。