Spring Batch - Problemi di connessione al database Postgres

Aug 25 2020

Fino ad ora avevo utilizzato H2 DB in memoria con Spring Batch. Tuttavia, ora sono passato alla connessione al DB postgres esterno. Ecco il mio oggetto di connessione (con qualche offuscamento):

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

Quando avvio la mia applicazione, ottengo:

Causato da: org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; grammatica SQL errata [SELECT JOB_INSTANCE_ID, JOB_NAME da BATCH_JOB_INSTANCE dove JOB_NAME = ? e JOB_KEY = ?]; l'eccezione nidificata è org.postgresql.util.PSQLException: ERRORE: la relazione "batch_job_instance" non esiste

Ho quindi letto che Spring Batch utilizza il database per salvare i metadati per la sua funzionalità di recupero/riprova e, con i database incorporati, queste sono le tabelle che Spring Batch imposta per impostazione predefinita. Ok, questo spiegherebbe perché non avevo mai visto questo errore prima.

Tuttavia, ha detto che potevo impostare questa proprietà:

spring.batch.initialize-schema=never

Quindi l'ho inserito nel mio file application.properties. Tuttavia, sto ancora ricevendo l'errore. Sarei grato per qualsiasi idea.

Risposte

TimothyClotworthy Aug 25 2020 at 19:24

Sono stato in grado di affrontarlo da solo. Alla fine avevo bisogno del repository Spring Batch indipendente dal mio attuale database relazionale di destinazione. Allora ho trovato questo riferimento:

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

Sono stato in grado di prendere la classe DefaultBatchConfigurer da quell'esempio e apportare una piccola modifica all'origine dati aggiungendo @Qualifier per l'origine dati incorporata/locale:

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

Quindi, sul mio lettore Spring Batch (nell'altra mia classe di configurazione batch), ho apportato una piccola modifica all'origine dati aggiungendo @Qualifier per l'origine dati postgres:

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

Quindi, infine (o in primo luogo proprio come ho fatto prima), ho chiamato esplicitamente i miei bean di origine dati in modo che Java potesse distinguerli per usarli come sopra:

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

Dopo aver fatto tutto quanto sopra, l'errore è scomparso e tutto ha funzionato.