我知道我可以直接从step1读取文件,在将sql查询设置到阅读器之前的那一刻,但我希望将查询的过程与数据库读取分开。
这是我的工作配置。
@Configuration
public class BatchConfiguration {
[...]
@Bean
@StepScope
public JdbcCursorItemReader<Map<String, Object>> dynamicSqlItemReader() {
JdbcCursorItemReader<Map<String, Object>> jir = new JdbcCursorItemReader<>();
jir.setSql((String) contextHolder.getContext().get("fileContent"));
jir.setDataSource(dataSource);
jir.setRowMapper(new ColumnMapRowMapper());
return jir;
}
private FlatFileItemReader<String> flatFileItemReader() {
[...]
}
private ItemWriter<? super String> sysoItemWriter() {
return (ItemWriter<String>) list -> {
for (String element : list) {
System.out.println(element);
}
contextHolder.getContext().put("fileContent", list.get(0));
};
}
@Bean
public ItemWriter<Map<String, Object>> customerItemWriter() {
return list -> {
for (Map<String, Object> stringObjectMap : list) {
System.out.println(stringObjectMap);
}
};
}
@Bean
public Step step0() {
return stepBuilderFactory.get("step0")
.<String, String>chunk(1)
.reader(flatFileItemReader())
.writer(sysoItemWriter())
.build();
}
@Bean
public Step step1() {
return stepBuilderFactory.get("step1")
.<Map<String, Object>, Map<String, Object>>chunk(10)
.reader(dynamicSqlItemReader())
.writer(customerItemWriter())
.build();
}
@Bean
public Job job() throws Exception {
return jobBuilderFactory.get("job")
.incrementer(new RunIdIncrementer())
.start(step0())
.next(step1())
.build();
}
}
这会引发java.lang.IllegalArgumentException: The SQL query must be provided
,因为contextHolder.getContext().get("fileContent")
在设置查询时仍为null
。
答案 0 :(得分:0)
在第1步之前,您可以编写一个用于构建查询并将其放入上下文的tasklet,以便它保持独立,并且它也可用于step1。在此处查看有关tasklet的更多信息:Tasklet to delete a table in spring batch
答案 1 :(得分:0)
您没有正确使用创建的contextHolder
,因为其值为null。
确保您将flatFileItemReader()
中的数据直接放在contextHolder
中作为地图,因为当您获得价值时,您正在使用contextholder.getContext()
。由于它是一个简单的地图,而不是ApplicationContext
,因此您使用的方法不存在。