web-dev-qa-db-ja.com

Spring Batchでの複数のDataSourceの使用

Spring Batch内でいくつかのデータソースを設定しようとしています。起動時に、Spring Batchは次の例外をスローします。

To use the default BatchConfigurer the context must contain no more thanone DataSource, found 2

バッチ構成からのスニペット

@Configuration
@EnableBatchProcessing 
public class BatchJobConfiguration {

    @Primary
    @Bean(name = "baseDatasource")
    public DataSource dataSource() {
         // first datasource definition here
    }
    @Bean(name = "secondaryDataSource")
    public DataSource dataSource2() {
         // second datasource definition here
    }
    ...
}

複数のデータソースを宣言するSpringバッチのxmlベースの構成を見たため、この例外が発生する理由がわかりません。 Spring Bootバージョン1.1.5.RELEASEでSpring Batchコアバージョン3.0.1.RELEASEを使用しています。どんな助けも大歓迎です。

31
Ahmed Bhaila

独自のBatchConfigurerを提供する必要があります。春はあなたのためにその決定をしたくない

@Configuration
@EnableBatchProcessing
public class BatchConfig {

     @Bean
      BatchConfigurer configurer(@Qualifier("batchDataSource") DataSource dataSource){
        return new DefaultBatchConfigurer(dataSource);
      }

...
22
PeterSan

最も簡単な解決策は、DefaultBatchConfigurerを拡張し、修飾子を介してデータソースを自動接続することです。

@Component
public class MyBatchConfigurer extends DefaultBatchConfigurer {

    /**
     * Initialize the BatchConfigurer to use the datasource of your choosing
     * @param firstDataSource
     */
    @Autowired
    public MyBatchConfigurer(@Qualifier("firstDataSource") DataSource firstDataSource) {
        super(firstDataSource);
    }
}

サイドノート(これは複数のデータソースの使用も扱うため):autoconfigを使用してデータ初期化スクリプトを実行する場合、期待するデータソースで初期化されないことに気付くかもしれません。その問題については、これを見てください: https://github.com/spring-projects/spring-boot/issues/9528

2
user3474985

ここでソリューションを提供したいと思います。これは@vanarchiが回答したものと非常によく似ていますが、必要なすべての構成を1つのクラスにまとめることができました。

完全を期すために、ここでのソリューションはプライマリデータソースがhsqlであると仮定しています。

_@Configuration
@EnableBatchProcessing
public class BatchConfiguration extends DefaultBatchConfigurer {

@Bean
@Primary
public DataSource batchDataSource() {

    // no need shutdown, EmbeddedDatabaseFactoryBean will take care of this
    EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
    EmbeddedDatabase embeddedDatabase = builder
            .addScript("classpath:org/springframework/batch/core/schema-drop-hsqldb.sql")
            .addScript("classpath:org/springframework/batch/core/schema-hsqldb.sql")
            .setType(EmbeddedDatabaseType.HSQL) //.H2 or .DERBY
            .build();
    return embeddedDatabase;
}

@Override
protected JobRepository createJobRepository() throws Exception {
    JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
    factory.setDataSource(batchDataSource());
    factory.setTransactionManager(transactionManager());
    factory.afterPropertiesSet();

    return (JobRepository) factory.getObject();
}

private ResourcelessTransactionManager transactionManager() {
    return new ResourcelessTransactionManager();
}

//NOTE: the code below is just to provide developer an easy way to access the in-momery hsql datasource, as we configured it to the primary datasource to store batch job related data. Default username : sa, password : ''
@PostConstruct
public void getDbManager(){
    DatabaseManagerSwing.main(
            new String[] { "--url", "jdbc:hsqldb:mem:testdb", "--user", "sa", "--password", ""});
}
_

}

このソリューションの3つのキーポイント:

  1. このクラスには_@EnableBatchProcessing_および_@Configuration_の注釈が付けられ、DefaultBatchConfigurerから拡張されます。これを行うことで、AbstractBatchConfigurationBatchConfigurerを検索しようとするときに、カスタマイズされたバッチ構成を使用するようにspring-batchに指示します。
  2. BatchDataSource Beanに_@Primary_として注釈を付けます。これは、9つのジョブ関連テーブルを格納するデータソースとしてこのデータソースを使用するようにspring-batchに指示します。
  3. protected JobRepository createJobRepository() throws Exceptionメソッドをオーバーライドします。これにより、jobRepository Beanはプライマリデータソースを使用し、他のデータソースとは異なるtransactionManagerインスタンスを使用します。
1
imarchuang

上記の質問に追加する場合、DSごとに1つのトランザクションコンテキストを2つ持つことの意味。ステップレベルでTXN管理を確保する必要があるため、XAトランザクションをバッチステップに統合する方法要件は、次が必要なバッチステップのようなものです。

  1. 読み取りDS 1-jpaItemReader
  2. dS2への書き込み-JPAItemwriter
  3. dS2から読み取る-JPAItemreader
  4. ds1への書き込み-JPAItemwriter
  5. すべてのtxnsステップを完了しました。
1
saiD

最初に、カスタムBatchConfigurerを作成します

@Configuration
@Component
public class TwoDataSourcesBatchConfigurer implements BatchConfigurer {

    @Autowired
    @Qualifier("dataSource1")
    DataSource dataSource;

    @Override
    public JobExplorer getJobExplorer() throws Exception {
        ...
    }

    @Override
    public JobLauncher getJobLauncher() throws Exception {
        ...
    }

    @Override
    public JobRepository getJobRepository() throws Exception {
        JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
        // use the autowired data source
        factory.setDataSource(dataSource);
        factory.setTransactionManager(getTransactionManager());
        factory.afterPropertiesSet();
        return factory.getObject();
    }

    @Override
    public PlatformTransactionManager getTransactionManager() throws Exception                      {
        ...
    }

}

その後、

@Configuration
@EnableBatchProcessing
@ComponentScan("package")
public class JobConfig {
    // define job, step, ...
}
0
Dayong