UGA Boxxx

つぶやきの延長のつもりで、知ったこと思ったこと書いてます

【MyBatis】spring-bootで2つのデータソースを利用する

spring-bootでMyBatisを使っていて、MyBatisを利用する時だけ別のデータソースを利用したい場合にどうやるのかわかったのでメモ

元々1つのデータソースを利用する場合は以下のようにapplication.yamlでプロパティの定義をしていたのだが、

spring:
  datasource:
    url: ${sm://backend-db-primay-url}
    username: ${sm://backend-db-primay-user}
    password: ${sm://backend-db-primay-password}

MyBatisを利用する時だけ、これは使わずに別のデータソースを利用したい

この2つ目のデータソースをsecondaryとすると、secondaryは上の設定が使えないので新たに以下のように定義した

spring:
  datasource:
    url: ${sm://backend-db-primay-url}
    username: ${sm://backend-db-primay-user}
    password: ${sm://backend-db-primay-password}

secondary:
  datasource:
    url: ${sm://backend-db-secondary-url}
    username: ${sm://backend-db-secondary-user}
    password: ${sm://backend-db-secondary-password}

springのデータソース設定から外れてしまうので、自前でMyBatisのデータソースをカスタマイズする実装が必要になる

対応方針

MybatisAutoConfigurationの実装を見たところ以下のようになっており、sqlSessionFactoryを自前で作ってBean登録すれば良さそうとわかった
※ @ConditionalOnMissingBeanは特定のBeanがApplicationContextに存在しない場合に有効化される

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

実装は以下のように行なった

@Configuration
public class SecondaryRepositoryConfiguration {

  @Bean
  @ConfigurationProperties("secondary.datasource")
  DataSourceProperties primaryDataDataSourceProperties() {
    return new DataSourceProperties();
  }

  @Bean(name = "secondaryDataSource")
  DataSource dataSource() {
    return primaryDataDataSourceProperties().initializeDataSourceBuilder().build();
  }

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

注意点として、dataSourceのBeanにはnameをつけてprimaryと区別できるようにしておく

これでMyBatisの時だけ別のデータソースを使うように設定することができた

他に、mybatis-spring-boot-autoconfigureConfigurationCustomizerも使えれば良かったのかもしれないが、バージョンが合わなかったので今回は使わなかった