我创建了一个通用 Spring Batch 作业,用于处理数据并将其存储到 CSV 中。我需要一些来自阅读器的数据传递给我正在尝试使用 JobExecution 执行的编写器。然而令人惊讶的是,代码似乎首先调用 getWriter() 而不是 getReader() 函数。我的配置如下。有人可以解释为什么会发生这种情况,以及是否有其他方法可以将数据从读取器传递到写入器。
@Bean
@StepScope
public ItemReader<Map<String, Object>> getDataReader() throws Exception {
return springBatchReader.getReader();
}
@Bean
@StepScope
public FlatFileItemWriter<Map<String, Object>> getDataWriter() throws Exception {
return (FlatFileItemWriter<Map<String, Object>>) springBatchWriter.getWriter();
}
@Bean
public Job SpringBatchJob(Step generateReport) throws Exception {
return jobBuilderFactory.get("SpringBatchJob" + System.currentTimeMillis())
.preventRestart()
.incrementer(new RunIdIncrementer())
.flow(generateReport)
.end()
.build();
}
@Bean
public Step generateReport() throws Exception {
return stepBuilderFactory.get("generateReport").<Map<String, Object>, Map<String, Object>>chunk(batchSize)
.reader(getDataReader()).writer(getDataWriter()).build();
}
我想从 Reader 传递给 Writer 的数据是 CSV 的列名。由于我的阅读器运行可变 SQL 查询(传递 SQL 查询以作为命令行参数运行),因此结果集/列不是静态的,而是根据给定的查询而变化。在 setHeaderCallback 中向 writer 提供要为特定执行写入的列名是从 Reader 向 Writer 发送数据的基本原理。
由于数据的可变性,Reader simple 运行给定的查询并将数据放入 Map<String, Object> 而不是任何 POJO。这里 Map 的键代表列名,而相应的对象保存该列的值。所以本质上我希望作者 setHeaderCallback 能够访问传递的 Map 的键或以某种方式将键从 Reader 传递给 Writer。
编写器代码如下:
public FlatFileItemWriter<Map<String, Object>> getWriter() throws Exception {
String reportName = getReportName();
saveToContext(reportName, reportPath);
FileSystemResource resource = new FileSystemResource(String.join(File.separator, reportPath, getReportName()));
FlatFileItemWriter<Map<String, Object>> flatFileItemWriter = new FlatFileItemWriter<>();
flatFileItemWriter.setResource(resource);
//NEED HELP HERE..HOW TO SET THE HEADER TO BE THE KEYS OF THE MAP
//flatFileItemWriter.setHeaderCallback();
flatFileItemWriter.setLineAggregator(new DelimitedLineAggregator<Map<String, Object>>() {
{
setDelimiter(delimiter);
setFieldExtractor(
new PassThroughFieldExtractor<>()
);
}
});
flatFileItemWriter.afterPropertiesSet();
return flatFileItemWriter;
}