Spring Batch: problemas para conectarse a la base de datos de Postgres
Hasta ahora había estado usando H2 DB en memoria con Spring Batch. Sin embargo, ahora cambié a conectarme a una base de datos postgres externa. Aquí estaba mi objeto de conexión (con algo de ofuscación):
@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;
}
Cuando inicio mi aplicación, obtengo:
Causado por: org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; mala gramática SQL [SELECCIONE JOB_INSTANCE_ID, JOB_NAME from BATCH_JOB_INSTANCE where JOB_NAME = ? y CLAVE_TRABAJO = ?]; la excepción anidada es org.postgresql.util.PSQLException: ERROR: la relación "batch_job_instance" no existe
Luego leí que Spring Batch usa la base de datos para guardar metadatos para su funcionalidad de recuperación/reintento, y con bases de datos integradas, estas son tablas que Spring Batch configura de forma predeterminada. Ok, eso explicaría por qué nunca antes había visto este error.
Sin embargo, dijo que podía establecer esta propiedad:
spring.batch.initialize-schema=never
Así que puse esto en mi archivo application.properties. Sin embargo, sigo recibiendo el error. Estaría agradecido por cualquier idea.
Respuestas
Pude abordar esto yo mismo. En última instancia, necesitaba el repositorio de Spring Batch independiente de mi base de datos relacional de destino real. Así que encontré esta referencia:
https://github.com/spring-projects/spring-batch/blob/342d27bc1ed83312bdcd9c0cb30510f4c469e47d/spring-batch-core/src/main/java/org/springframework/batch/core/configuration/annotation/DefaultBatchConfigurer.java#L84
Pude tomar la clase DefaultBatchConfigurer de ese ejemplo y hacer un cambio menor en la fuente de datos agregando el @Qualifier para la fuente de datos incrustada/local:
@Autowired(required = false)
public void setDataSource(@Qualifier("dataSource") DataSource dataSource) {
this.dataSource = dataSource;
this.transactionManager = new DataSourceTransactionManager(dataSource);
}
Luego, en mi lector Spring Batch (en mi otra clase de configuración por lotes), hice un cambio menor en la fuente de datos al agregar el @Qualifier para la fuente de datos de 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();
}
Luego, por último (o en primer lugar realmente como lo hice primero), nombré explícitamente mis beans de fuente de datos para que Java pudiera diferenciarlos para usarlos como se indica arriba:
@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; }
}
Una vez que hice todo lo anterior, el error desapareció y todo funcionó.