首页 > 解决方案 > 在 Spring Batch 中展平列表列表的最佳方法是什么?

问题描述

在 Spring Batch 中,处理器从一种输入类型映射到一种输出类型。但是我需要List<O>从一个生成输出类型 ()的列表I

处理器可以返回List<O>就好了,但假设我想在后续处理器中作为个体使用这个列表的元素。我应该先将它们写入数据库吗?事实上,我从远程服务中得到了一些丰富,需要对每个成员进行处理,List<O>所以我不希望它们写在任何地方,直到可以处理列表中的各个对象。

这与我的上一篇文章有​​关,其中有人告诉我,@JobScope步骤之间的内存中对象传输有 90% 是代码异味。我很好奇我是否在这里错过了一个特殊的 Spring Batch 模式,用于展平列表的结果列表,这与在处理之前将半生不熟的对象写入数据库、缓存或平面文件不同。

但最终我希望作者使用一大块而O不是一大块List<O>. 那么推荐的方法是什么?到目前为止,我想出了以下用作@JobScopebean:

public class FlatMapPipe<T> implements ItemWriter<List<T>>, ItemReader<T> {

    private LinkedList<List<T>> lists = new LinkedList<List<T>>();

    /**
     * Pages through the internal linked list to find the next item
     * @return next item in the current list or the first item in the next list or null
     * @throws Exception
     * @throws UnexpectedInputException
     * @throws ParseException
     * @throws NonTransientResourceException
     */
    @Override
    public T read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
        if (lists.size() == 0) {
            return null;
        }
        List<T> list = lists.get(0);
        if (list.isEmpty()) {
            lists.remove();
            return read();
        } else {
            return list.remove(0);
        }
    }

    /**
     * Appends a list to the linked list of lists of written Items
     * @param list
     * @throws Exception
     */
    @Override
    public void write(List<? extends List<T>> list) throws Exception {
        list.forEach((it) -> lists.add(new ArrayList<>(it)));
    }
} 

标签: spring-batch

解决方案


处理器可以很好地返回列表,但假设我想将此列表的元素作为后续处理器中的个体使用。我应该先将它们写入数据库吗?

不需要先将它们写入数据库,那将是低效的。封装是您的朋友,您可以将处理器的结果包装在一个聚合类型中,该类型可以传递给链中的后续处理器(例如使用复合处理器)。然后,项目编写器负责执行平面映射操作,以便在写入之前从聚合类型中解开完全处理的项目。

另一种技术是使用两个并发步骤和一个暂存区域(您将在其中展平项目),如问题 #2044中所述。我在这里实现了一个 PoC ,其中一个阻塞队列作为暂存区。在您的情况下,第一步将处理项目并将结果写入队列,第二步可以从队列中读取(平面)项目,根据需要丰富它们并在适当的地方写入它们。


推荐阅读