Mybatisでdatasourceを動的に切り替える方法

Mybatisでdatasourceを動的に切り替える方法

MyBatisでデータソースを動的に切り替える方法はいくつかありますが、一般的には以下の手順を踏むことが多いです。

1. 動的データソースの定義

動的データソースを管理するためのクラスを作成します。

public class DynamicDataSource extends AbstractRoutingDataSource {

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

2. データソースのコンテキストホルダー

スレッドローカル変数を使って、現在のデータソースタイプを管理します。

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();
    }
}

3. データソースの設定

複数のデータソースを設定し、DynamicDataSourceにマップします。

@Configuration
public class DataSourceConfig {

    @Bean
    @Primary
    public DataSource dataSource() {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();

        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put("dataSource1", dataSource1());
        targetDataSources.put("dataSource2", dataSource2());

        dynamicDataSource.setTargetDataSources(targetDataSources);
        dynamicDataSource.setDefaultTargetDataSource(dataSource1());

        return dynamicDataSource;
    }

    @Bean
    public DataSource dataSource1() {
        return DataSourceBuilder.create().url("jdbc:mysql://localhost:3306/db1").username("user1").password("password1").build();
    }

    @Bean
    public DataSource dataSource2() {
        return DataSourceBuilder.create().url("jdbc:mysql://localhost:3306/db2").username("user2").password("password2").build();
    }
}

4. AOPを使ってデータソースを切り替える

特定の条件やメソッド実行時にデータソースを切り替えるために、AOPを使用します。

@Aspect
@Component
public class DataSourceAspect {

    @Pointcut("execution(* com.example.service.*.*(..))")
    public void serviceMethods() {}

    @Before("serviceMethods() && @annotation(com.example.annotation.DataSource)")
    public void switchDataSource(JoinPoint point) {
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        DataSource dataSource = method.getAnnotation(DataSource.class);
        if (dataSource != null) {
            DataSourceContextHolder.setDataSourceType(dataSource.value());
        } else {
            DataSourceContextHolder.clearDataSourceType();
        }
    }

    @After("serviceMethods()")
    public void clearDataSource(JoinPoint point) {
        DataSourceContextHolder.clearDataSourceType();
    }
}

5. データソースアノテーション

メソッドにデータソースを指定するためのアノテーションを作成します。

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface DataSource {
    String value();
}

6. アノテーションの適用

サービスメソッドにデータソースを指定するためのアノテーションを適用します。

@Service
public class MyService {

    @Autowired
    private MyMapper myMapper;

    @DataSource("dataSource1")
    public void methodUsingDataSource1() {
        // データベース操作
    }

    @DataSource("dataSource2")
    public void methodUsingDataSource2() {
        // データベース操作
    }
}

この方法で、MyBatisとSpringBootを使用して動的にデータソースを切り替えることができます。