Apr 8, 2025
Apr 8, 2025
N/A Views
MD

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=
Found a mistake? Update the entry.
Share this article: