今回は、DatasourceをMaster、Slaveに分ける方法について調べていきたいと思います。
DataSourceとは
Javaのjavax.sql.DataSource インターフェースは、データベース接続を操作する標準的な方法を提供します。伝統的に、”DataSource” は、URLといくつかの資格情報を使用してデータベース接続を確立します。
DataSourceを分ける
application.yml作成
spring:
datasource:
master:
username: root
password: password
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://localhost:3306/sampledb
slave:
username: root
password: password
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://localhost:3307/sampledb
MasterとSlaveのDBを2つ使用するために、Datasource生成作業を実装しなければなりません。
DataSourceConfig作成
@Configuration
public class DataSourceConfig {
@Bean(name = "dataSource")
public DataSource dataSource(
@Autowired @Qualifier("routingDataSource") DataSource routingDataSource) {
return new LazyConnectionDataSourceProxy(routingDataSource);
}
@Bean(name = "routingDataSource")
@Primary
public DataSource routingDataSource(
@Autowired @Qualifier("masterDataSource") DataSource masterDataSource,
@Autowired @Qualifier("slaveDataSource") DataSource slaveDataSource) {
RoutingDataSource routingDataSource = new RoutingDataSource();
Map<Object, Object> dataSourceMap = new HashMap<>();
dataSourceMap.put("master", masterDataSource);
dataSourceMap.put("slave", slaveDataSource);
routingDataSource.setTargetDataSources(dataSourceMap);
routingDataSource.setDefaultTargetDataSource(masterDataSource);
return routingDataSource;
}
@Bean(name = "masterDataSource")
@ConfigurationProperties(prefix = "spring.datasource.master")
public DataSource masterDataSource() {
return DataSourceBuilder.create().type(HikariDataSource.class).build();
}
@Bean(name = "slaveDataSource")
@ConfigurationProperties(prefix = "spring.datasource.slave")
public DataSource slaveDataSource() {
return DataSourceBuilder.create().build();
}
}
- 設定クラスなので「Configuration」アノテーションを付与します。
- routingDataSource
- MasterとSlaveのDataSourceとして登録します。
- デフォルトとしてはMaster DataSourceを指定します。
- masterDataSource
- プロパティからmaster DB情報を取得し、DataSourceを返します。
- 「masterDataSource」としてBeanを登録します。
- slaveDataSource
- masterDataSourceメソッドと同様ですが、master db情報ではなく、slave db情報でDataSourceを生成して返します。
RoutingDataSource作成
public class RoutingDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return TransactionSynchronizationManager.isCurrentTransactionReadOnly() ? "slave" : "master";
}
}
- AbstractRoutingDataSource:照会keyで登録されているDataSourceの中で一つを呼び出せます。
- determineCurrentLookupKey:現在、照会キーを返却できるように実装しなければなりません。
- ここではMasterとSlaveと指定しています。
- readOnly属性の場合はslave Datasourceが返却されるように実装します。
- DataSourceConfigクラスのroutingDataSourceメソッドから呼ばれます。
使い方
@Transactional(readOnly = true)
public List<Some> get(){
return someRepository.findAll();
}
public int update() {
SomEntity someEntity = new SomeEntity();
return someRepository.update(someEntity);
}
- Transactionalアノテーションの属性として「readOnly=true」なので、RoutingDataSourceによるslave Datasourceを利用してデータを取得します。
- update:何も指定していないため、master Datasourceを利用してデータをアップデートします。
参考
https://spring.pleiades.io/spring-boot/docs/2.1.4.RELEASE/reference/html/boot-features-sql.html
