Spring Batch + Spring BootでJob内で利用するデータベースとJobを管理するデータベースを別々にするメモ

Spring BatchでJob内で利用するデータベースとJobを管理するデータベースを別々にする方法は、Spring Bootのドキュメントに書かれているのですが、実装例がないのでメモしておきます。

Spring Boot 3.4, Spring Batch 5.2で動作確認しました。

次のようなConfigクラスを用意しておけば良いです。

package com.example.batch;

import com.zaxxer.hikari.HikariDataSource;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.batch.BatchDataSource;
import org.springframework.boot.autoconfigure.batch.BatchTransactionManager;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.support.JdbcTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(name = "spring.batch.datasource.url")
public class DataSourceConfig {

	@Bean
	@ConfigurationProperties("spring.datasource")
	public DataSourceProperties defaultDataSourceProperties() {
		return new DataSourceProperties();
	}

	@Bean
	@ConfigurationProperties("spring.datasource.hikari")
	public HikariDataSource defaultDataSource(
			@Qualifier("defaultDataSourceProperties") DataSourceProperties properties) {
		HikariDataSource dataSource = properties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
		dataSource.setPoolName("default-pool");
		return dataSource;
	}

	@Bean
	@ConfigurationProperties("spring.batch.datasource")
	public DataSourceProperties batchDataSourceProperties() {
		return new DataSourceProperties();
	}

	@BatchDataSource
	@Bean(defaultCandidate = false)
	@ConfigurationProperties("spring.batch.datasource.hikari")
	public HikariDataSource batchDataSource(@Qualifier("batchDataSourceProperties") DataSourceProperties properties) {
		HikariDataSource dataSource = properties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
		dataSource.setPoolName("batch-pool");
		return dataSource;
	}

	@BatchTransactionManager
	@Bean(defaultCandidate = false)
	public PlatformTransactionManager batchTransactionManager(@BatchDataSource DataSource dataSource) {
		return new JdbcTransactionManager(dataSource);
	}

}

@Bean(defaultCandidate = false)をつけることによって@Qualifier(@BatchDataSource@BatchTransactionManagerを含む)で明示しない限り、インジェクションの対象となりません。 Spring BootのAuto Configurationでは、JobRepositoryJobExplorerを作成する際に@BatchDataSource@BatchTransactionManagerアノテーションが付いたBean定義があればそちらを使うようになっています。

プロパティの設定例は次のとおりです。

spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://localhost:5432/mydatabase
spring.datasource.username=myuser
spring.datasource.password=secret
spring.batch.datasource.driver-class-name=org.postgresql.Driver
spring.batch.datasource.url=jdbc:postgresql://localhost:15432/spring_batch
spring.batch.datasource.username=spring_batch
spring.batch.datasource.password=admin

spring.datasource.*にJob内で利用するデータベースを設定します。これは通常のデータベースの設定と同じプロパティを使うようにしました。 spring.batch.datasource.*にJobを管理するデータベースを設定します。 @ConditionalOnProperty(name = "spring.batch.datasource.url")がついているため、spring.batch.datasource.urlでJobを管理するデータベースの設定を明示的に行った時のみ上記のConfigが有効になります。 spring.batch.datasource.urlの指定がない場合はデフォルトのAuto Configurationのままです。

この例では、Job内で利用するデータベースとJobを管理するデータベースの両方にPostgreSQLを使用していますが、別のデータベースでも構いません。 例えば、次のような定義にすれば、Jobを管理するデータベースにインメモリのH2データベースを利用できます。

spring.batch.datasource.url=jdbc:h2:mem:spring_batch
spring.batch.datasource.driverClassName=org.h2.Driver
spring.batch.datasource.username=sa
spring.batch.datasource.password=