Spring Batch - 在读取器处理器和写入器之间传递所有数据

我很好奇如何设法将读取器中的所有可用数据传递到管道中 .

例如我希望读者将所有数据拉入并将整个结果集传递给处理器和编写器 . 结果集很小,我不担心资源 . 我以为我已经通过让所有组件(阅读器,编写器,处理器)接收并返回已处理项目的集合来正确实现这一点 .

虽然这个过程的结果看起来很好,但我所看到的是,这个工作正在读取所有内容,将其传递到管道中,然后返回到读取器,读取所有内容并将其传递下去,依此类推 .

我已经考虑创建一个额外的步骤来读取所有数据并将其传递给后续步骤,但我很好奇我是否可以这样做以及如何

工作看起来像

@Bean
Job job() throws Exception {
    return jobs.get("job").start(step1()).build()
}
@Bean
protected Step step1() throws Exception {
    return steps.get("step1").chunk(10)
    .reader(reader()
    .processor(processor()
    .writer(writer()).build()

// ....

读取器,处理器和写入器接受并返回List,例如

class DomainItemProcessor implements ItemProcessor<List<Domain>, List<Domain>>{

回答(2)

2 years ago

您还可以将其实现为tasklet . 由于您希望一次处理所有数据,因此您实际上没有批处理,因此,根本不会使用“正常” spring 批处理步骤的整个重启和失败处理 .

像这样的tasklet在伪代码中看起来如下:

@Component
public class MyTasklet implements Tasklet {

    @Autowired
    private ItemReader<YourType> readerSpringBeanName;

    @Autowired
    private ItemProcessor<List<YourType>,List<YourType>> processorSpringBeanName;

    @Autwired
    private ItemWriter<List<YourType>> writerSpringBeanName;


    RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) {
        readerSpringBeanName.open(new ExecutionContext());
        writerSpringBeanName.open(new ExecutionContext());

        List<YourType> items = new ArrayList<>();
        YourType readItem = readerSpringBeanName.read();
        while(readItem != null) {
             items.add(readItem);
             readItem = readerSpringBeanName.read();
        }

        writerSpringBeanName.write(processorSpringBeanName.process(items));

        readerSpringBeanName.close();
        writerSpringBeanName.close();
        return RepeatStatus.FINISHED;
    }
}

此外,根据您的使用情况,甚至可能根本不需要定义 spring 批作业 .

2 years ago

这种情况下的高级设计将是

  • Reader将是一个自定义阅读器 . 它将返回List或包含Domain对象列表的包装器 . 读者将注入一个DAO bean来执行查询并检索域列表 .

公共类DomainList {private List domains;

// get/set

}

公共类DomainReader实现ItemReader {

@Autowire
private DomainDAO domainDAO;

private List<Domain> domains;

@Override
public DomainList read() throws Exception {
    if (this.domains == null) {
        // TODO: please replace with your business logic.
        this.domains = this.domainDAO.getListofDomains();
        return this.domains;
    }
    else {
        return null;   // to tell Spring Batch the reader has done.
    }
}

}

  • Processor和Writer将DomainList作为输入 .

注意:上面是伪代码 .

谢谢,Nghia