Spring Batch - Masalah Menghubungkan ke Database Postgres

Aug 25 2020

Sampai sekarang saya telah menggunakan H2 DB dalam memori dengan Spring Batch. Namun, sekarang saya beralih ke koneksi ke DB postgres eksternal. Inilah objek koneksi saya (dengan beberapa kebingungan):

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

Ketika saya memulai aplikasi saya, saya mendapatkan:

Disebabkan oleh: org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; tata bahasa SQL buruk [SELECT JOB_INSTANCE_ID, JOB_NAME dari BATCH_JOB_INSTANCE dimana JOB_NAME =? dan JOB_KEY =?]; pengecualian bersarang adalah org.postgresql.util.PSQLException: ERROR: relasi "batch_job_instance" tidak ada

Saya kemudian membaca bahwa Spring Batch menggunakan database untuk menyimpan metadata untuk fungsi pemulihan / coba lagi, dan dengan database yang disematkan, ini adalah tabel yang disiapkan Spring Batch secara default. Oke, jadi itu akan menjelaskan mengapa saya belum pernah melihat kesalahan ini sebelumnya.

Namun, dikatakan saya dapat menyetel properti ini:

spring.batch.initialize-schema=never

Jadi saya meletakkan ini di file application.properties saya. Namun, saya masih mendapatkan kesalahan tersebut. Saya akan berterima kasih atas ide apa pun.

Jawaban

TimothyClotworthy Aug 25 2020 at 19:24

Saya bisa mengatasi ini sendiri. Pada akhirnya saya membutuhkan repositori Spring Batch independen dari database relasional target saya yang sebenarnya. Jadi saya menemukan referensi ini:

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

Saya dapat mengambil kelas DefaultBatchConfigurer dari contoh itu dan membuat perubahan kecil pada sumber data dengan menambahkan @Qualifier untuk sumber data tertanam / lokal:

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

Kemudian, pada pembaca Spring Batch saya (di kelas config batch saya yang lain), saya membuat perubahan kecil pada sumber data dengan menambahkan @Qualifier untuk sumber data 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();
}

Kemudian terakhir (atau pertama benar-benar seperti yang saya lakukan ini pertama), saya secara eksplisit menamai kacang sumber data saya sehingga java dapat membedakannya untuk digunakan seperti di atas:

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

Setelah saya melakukan semua hal di atas, kesalahan menghilang dan semuanya berfungsi.