Spring Batch - Problèmes de connexion à la base de données Postgres

Aug 25 2020

Jusqu'à présent, j'utilisais une base de données H2 en mémoire avec Spring Batch. Cependant, je suis maintenant passé à la connexion à une base de données postgres externe. Voici mon objet de connexion (avec un peu d'obscurcissement):

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

Lorsque je lance mon application, j'obtiens :

Causé par : org.springframework.jdbc.BadSqlGrammarException : PreparedStatementCallback ; mauvaise grammaire SQL [SELECT JOB_INSTANCE_ID, JOB_NAME de BATCH_JOB_INSTANCE où JOB_NAME = ? et JOB_KEY = ?] ; l'exception imbriquée est org.postgresql.util.PSQLException : ERREUR : la relation "batch_job_instance" n'existe pas

J'ai ensuite lu que Spring Batch utilise la base de données pour enregistrer les métadonnées pour sa fonctionnalité de récupération/réessaie, et avec les bases de données intégrées, ce sont des tables que Spring Batch configure par défaut. Ok, cela expliquerait pourquoi je n'avais jamais vu cette erreur auparavant.

Cependant, il a dit que je pouvais définir cette propriété:

spring.batch.initialize-schema=never

J'ai donc mis cela dans mon fichier application.properties. Cependant, je reçois toujours l'erreur. Je serais reconnaissant pour toutes les idées.

Réponses

TimothyClotworthy Aug 25 2020 at 19:24

J'ai pu régler cela moi-même. En fin de compte, j'avais besoin du référentiel Spring Batch indépendant de ma base de données relationnelle cible réelle. J'ai donc trouvé cette référence :

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

J'ai pu prendre la classe DefaultBatchConfigurer de cet exemple et apporter une modification mineure à la source de données en ajoutant le @Qualifier pour la source de données intégrée/locale :

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

Ensuite, sur mon lecteur Spring Batch (dans mon autre classe de configuration batch), j'ai apporté une modification mineure à la source de données en ajoutant le @Qualifier pour la source de données 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();
}

Puis enfin (ou tout d'abord vraiment comme je l'ai fait en premier), j'ai explicitement nommé mes beans de source de données afin que java puisse les distinguer pour les utiliser comme ci-dessus :

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

Une fois que j'ai fait tout ce qui précède, l'erreur a disparu et tout a fonctionné.