Spring 批处理 - 连接到 Postgres 数据库时出现问题

Spring Batch - Problems Connecting to Postgres Database

到目前为止,我一直在使用内存中的 H2 DB 和 Spring Batch。但是,现在我切换到连接到外部 postgres 数据库。这是我的连接对象(有些混淆):

@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;
}

当我启动我的应用程序时,我得到:

Caused by: org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [SELECT JOB_INSTANCE_ID, JOB_NAME from BATCH_JOB_INSTANCE where JOB_NAME = ? and JOB_KEY = ?]; nested exception is org.postgresql.util.PSQLException: ERROR: relation "batch_job_instance" does not exist

然后我读到 Spring Batch 使用数据库来保存其 recover/retry 功能的元数据,对于嵌入式数据库,这些表是 Spring Batch 默认设置的。好的,这就解释了为什么我以前从未见过这个错误。

然而,它说我可以设置这个属性:

spring.batch.initialize-schema=never

所以我把它放在我的 application.properties 文件中。但是,我仍然收到错误。如果有任何想法,我将不胜感激。

我自己解决了这个问题。最终,我需要独立于我的实际目标关系数据库的 Spring Batch 存储库。所以我找到了这个参考:

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 class 并通过为 embedded/local 数据源添加 @Qualifier 对数据源进行较小的更改:

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

然后,在我的 Spring 批处理 reader 上(在我的其他批处理配置 class 中),我通过为 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;    }
}

完成上述所有操作后,错误消失,一切正常。