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-autoconfigure
のConfigurationCustomizerも使えれば良かったのかもしれないが、バージョンが合わなかったので今回は使わなかった