概要
・メインDBにメタテーブルを生成したくない
・Repositoryを利用していない
・でもJdbcTemplateを利用して簡単にテーブルの操作がしたい
環境
Contents | Version |
---|---|
Java | 1.8 |
Spring Boot | 2.7.16 |
H2 | 2.1.214 |
実装方法
メタテーブル用とメインテーブル用でそれぞれDataSourceとJdbcTemplateを生成する
@Configuration
public class DataSourceConfiguration {
//メタテーブル用DataSource
@Bean("metaDataSource") //metaDataSourceという名前でBean登録
@BatchDataSource //メタテーブルの接続先に指定
@ConfigurationProperties(prefix = "spring.datasource.meta") //プロパティファイルのspring.datasource.meta.*を設定
public DataSource createMetaDataSource(){
return DataSourceBuilder.create().build();
}
//メインテーブル用DataSource
@Bean("mainDataSource") //mainDataSourceという名前でBean登録
@Primary //メインテーブルの接続先に指定
@ConfigurationProperties(prefix = "spring.datasource.main") //プロパティファイルのspring.datasource.main.*を設定
public DataSource createMainDataSource(){
return DataSourceBuilder.create().build();
}
//メタテーブル用JdbcTemplate
@Bean("metaJdbcTemplate") //metaJdbcTempalteという名前でBean登録
JdbcTemplate createMetaJdbcTemplate(@Qualifier("metaDataSource") DataSource ds){ //metaDataSourceを指定して引数として呼び出す
return new JdbcTemplate(ds);
}
//メインテーブル用JdbcTemplate
@Bean("mainJdbcTemplate") //mainJdbcTempalteという名前でBean登録
JdbcTemplate createMainJdbcTemplate(@Qualifier("mainDataSource") DataSource ds){ //mainDataSourceを指定して引数として呼び出す
return new JdbcTemplate(ds);
}
}
#SpringBatchの起動のたびにメタテーブルをインメモリDBに生成する必要があるためalwaysに設定
spring.batch.jdbc.initialize-schema=always
#メタテーブルの接続先情報
#※今回はメタテーブルを保持したくないのでインメモリDBのH2に生成し、メモリの解放とともに消えてもらう
spring.datasource.meta.username=sa
spring.datasource.meta.password=
spring.datasource.meta.jdbcUrl=jdbc:h2:mem:batch
#メインテーブルの接続先情報
spring.datasource.main.username=root
spring.datasource.main.password=root
spring.datasource.main.jdbcUrl=jdbc:mysql~~~
詳細
上記のソースでは、メタテーブルとメインテーブルのDataSourceをそれぞれ用意しています。それらを設定したJdbcTemplateをBean登録することで、メタテーブル用とメインテーブル用で使い分けられるようにしています。
@BatchDataSource
を付与したDataSourceはメタテーブルの管理に利用されるようになりますのでBean登録さえしておけば、spring.datasource.meta
に定義した接続先で勝手にメタテーブルを管理してくれます。
そして、メインテーブルを操作したいときはmainJdbcTemplate
のほうを@Qualifier
で指定して呼び出してあげればOKです。
@Component
public class SampleTasklet implements Tasklet {
@Autowired
@Qualifier("mainJdbcTemplate")
JdbcTemplate jdbcTemplate;
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext context){
jdbcTemplate.execute("INSERT INTO sample VALUES (1).... ");
}
}
トランザクション
DBにメタテーブルを保持せずにJdbcTemplateが利用できるようになりました!!
ただし、これではstepのトランザクション管理がメタテーブルのDBに貼られてしまいます。
メインテーブルのトランザクション管理をしたい場合は、transactionManagerを用意してあげましょう。
@Configuration
public class DataSourceConfiguration {
//~~~JdbcTemplateのコードの続き
@Bean("mainTransactionManager")
public PlatformTransactionManager mainTransactionManager(@Qualifier("mainJdbcTemplate") JdbcTemplate jdbcTemplate){
return new DataSourceTransactionManager(jdbcTemplate.getDataSource);
}
}
transactionManagerを作成したらトランザクション管理をしたい場所に設定することをお忘れなく
@Configuration
public class JobConfiguration {
@Autowired
@Qualifier("mainTransactionManager")
public PlatformTransactionManager mainTransactionManager;
@Bean("step1")
public Step step1(JobRepository jobRep){
return new StepBuilder("step1").repository(jobRep).transactionManager(mainTransactionManager)
.tasklet(sampleTasklet).build;
}
}
例外が発生したらメインDBをロールバックしてくれるようになりました!
これでメタテーブルは利用せず、管理せず、Springの便利機能を享受できるようになりました。
もっと美しく書くこともできそうではありますが、まずは機能を満たすことを優先ということで...