SpringBatch-Postgresデータベースへの接続の問題

Aug 25 2020

これまで、SpringBatchでインメモリH2DBを使用していました。しかし、今は外部のpostgresDBへの接続に切り替えました。これが私の接続オブジェクトでした(難読化されています):

@Bean
public DataSource postgresDatasource() {
    DriverManagerDataSource datasource = new DriverManagerDataSource();
    datasource.setDriverClassName("org.postgresql.Driver");
    datasource.setUrl("jdbc:postgresql://x.x.x.x:xxxx/blah");
    datasource.setUsername("Joe");
    datasource.setPassword("password");
    return datasource;
}

アプリケーションを起動すると、次のようになります。

原因:org.springframework.jdbc.BadSqlGrammarException:PreparedStatementCallback; 不正なSQL文法[SELECTJOB_INSTANCE_ID、JOB_NAME from BATCH_JOB_INSTANCE where JOB_NAME =?およびJOB_KEY =?]; ネストされた例外はorg.postgresql.util.PSQLExceptionです:エラー:リレーション "batch_job_instance"は存在しません

次に、Spring Batchがデータベースを使用して、リカバリ/再試行機能のメタデータを保存していることを読みました。組み込みデータベースでは、これらはSpringBatchがデフォルトで設定するテーブルです。さて、それは私が以前にこのエラーを見たことがなかった理由を説明するでしょう。

ただし、このプロパティを設定できるとのことです。

spring.batch.initialize-schema=never

だから私はこれを私のapplication.propertiesファイルに入れました。ただし、まだエラーが発生します。どんなアイデアでもありがたいです。

回答

TimothyClotworthy Aug 25 2020 at 19:24

私はこれに自分で対処することができました。最終的には、実際のターゲットリレーショナルデータベースから独立したSpringBatchリポジトリが必要でした。だから私はこの参照を見つけました:

https://github.com/spring-projects/spring-batch/blob/342d27bc1ed83312bdcd9c0cb30510f4c469e47d/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/DefaultBatchConfigurer.java#L84

その例からDefaultBatchConfigurerクラスを取得し、埋め込み/ローカルデータソースの@Qualifierを追加することで、データソースに小さな変更を加えることができました。

@Autowired(required = false)
public void setDataSource(@Qualifier("dataSource") DataSource dataSource) {
    this.dataSource = dataSource;
    this.transactionManager = new DataSourceTransactionManager(dataSource);
}

次に、Spring Batchリーダー(他のバッチ構成クラス)で、postgresデータソースの@Qualifierを追加して、データソースに小さな変更を加えました。

@Bean
public ItemReader<StuffDto> itemReader(@Qualifier("postgresDataSource")DataSource dataSource) {
return new JdbcCursorItemReaderBuilder<StuffDto>()
    .name("cursorItemReader")
    .dataSource(dataSource)
    .sql(GET_DATA)
    .rowMapper(new BeanPropertyRowMapper<>(StuffDto.class))
    .build();
}

次に最後に(または最初に最初に行ったように)、データソースBeanに明示的に名前を付けて、Javaが上記のように使用するように区別できるようにしました。

@Configuration
public class PersistenceContext {


    @Bean(name = "dataSource")
    public DataSource dataSource() {
        DriverManagerDataSource datasource = new DriverManagerDataSource();
        datasource.setDriverClassName("org.h2.Driver");
        datasource.setUrl("jdbc:h2:file:/tmp/test");
        datasource.setUsername("sa");
        datasource.setPassword("");
        return datasource;
    }

    @Bean(name = "postgresDataSource")
    public DataSource postgresDatasource() {
        DriverManagerDataSource datasource = new DriverManagerDataSource();
        datasource.setDriverClassName("org.postgresql.Driver");
        datasource.setUrl("jdbc:postgresql://x.x.x.x:xxxx/blah");
        datasource.setUsername("joe");
        datasource.setPassword("password");
        return datasource;    }
}

上記のすべてを実行すると、エラーは消え、すべてが機能しました。