在春季批次中展平处理结果

时间:2017-03-15 16:47:31

标签: java spring-batch

有没有人知道如何在spring-batch(3.0.7)中处理返回实体列表的处理器的结果? 例如:

我有一个返回List的处理器

public class MyProcessor implements ItemProcessor < Long , List <Entity>> {
    public List<Entity> process ( Long id )
}

现在所有后续处理器/编写器都需要在List&lt;实体&gt;。有没有办法将结果简化为Entity,以便给定步骤中的其他处理器可以处理单个实体?

唯一的方法是以某种方式使用编写器持久保存列表,然后创建一个可以从持久数据中读取的单独步骤。

提前致谢!

2 个答案:

答案 0 :(得分:0)

除非您能提供令人信服的理由,否则没有理由向您的ItemWriter发送列表清单。这不是ItemProcessor打算使用的方式。相反,您应该创建/配置和ItemReader以返回具有相关对象的一个​​对象。

例如,如果您正在从数据库中读取数据,则可以使用HibernateCursorItemReader和类似这样的查询:

"from ParentEntity parent left join fetch parent.childrenEntities"

您的数据模型应该有一个父表,其中包含您当前正在传递给Long id的{​​{1}},因此请利用这一优势。然后,读者将传回ItemProcessor个对象,每个对象都包含与其一起出现的ParentEntity个对象的集合。

答案 1 :(得分:0)

如您所知,spring-batch中的处理器可以使用复合处理器进行链接。在链中,您可以将处理类型从处理器更改为处理器,但当然两个&#34; neighbor&#34;处理器的输入和输出类型必须匹配。

但是,输出输出类型始终被视为一个项目。因此,如果处理器的输出类型是List,则此列表将被视为一个项目。因此,以下处理器需要具有InputType&#34; List&#34;,如果写入者遵循,则Writer需要具有List-of-List作为其写入方法的类型。 而且,处理器不能乘以其元素。每个输入元素只能有一个输出项。

基本上,拥有像

这样的链是没有错的
Reader<Integer>
ProcessorA<Integer,List<Integer>>
ProcessorB<List<Integer>,List<Integer>>
Writer<List<Integer>> (which leads to a write-method write(List<List<Integer>> items)

根据具体情况,可能会有更好的解决方案。 您可以通过使用包装器和包装器编写器来缓解影响(例如可重用性),如下面的代码示例所示:

public class ListWrapperProcessor<I,O> implements ItemProcessor<List<I>, List<O>> {

    ItemProcessor<I,O> delegate;

    public void setDelegate(ItemProcessor<I,O> delegate) {
        this.delegate = delegate;
    }


    public List<O> process(List<I> itemList) {
        List<O> outputList = new ArrayList<>();

        for (I item : itemList){    
           O outputItem = delegate.process(item);
           if (outputItem!=null) {
               outputList.add(outputItem);
           }
        }

        if (outputList.isEmpty()) {
            return null;
        }

        return outputList;
    }

}


public class ListOfListItemWriter<T> implements InitializingBean, ItemStreamWriter<List<T>> {

    private ItemStreamWriter<T> itemWriter;

    @Override
    public void write(List<? extends List<T>> listOfLists) throws Exception {
        if (listOfLists.isEmpty()) {
            return;
        }

        List<T> all = listOfLists.stream().flatMap(Collection::stream).collect(Collectors.toList());

        itemWriter.write(all);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        Assert.notNull(itemWriter, "The 'itemWriter' may not be null");
    }

    public void setItemWriter(ItemStreamWriter<T> itemWriter) {
        this.itemWriter = itemWriter;
    }

    @Override
    public void close() {
        this.itemWriter.close();
    }

    @Override
    public void open(ExecutionContext executionContext) {
        this.itemWriter.open(executionContext);
    }

    @Override
    public void update(ExecutionContext executionContext) {
        this.itemWriter.update(executionContext);
    }
}

使用这样的包装器,你仍然可以实现&#34; normal&#34;处理器和编写器然后使用这样的包装器来移动&#34; List&#34; - 处理它们。