【问题标题】:Spring Batch - Using an ItemWriter with List of ListsSpring Batch - 使用带有列表列表的 ItemWriter
【发布时间】:2016-10-18 09:23:19
【问题描述】:

我们的处理器返回一个List<?>(实际上是传递一个List<List<?>>)给我们的ItemWriter

现在,我们观察到 JdbcBatchItemWriter 未编程为处理 item instanceof List。我们还观察到处理 item instanceof List;我们需要编写一个自定义的ItemSqlParameterSourceProvider

但可悲的是它返回SqlParameterSource,它只能处理一个item,并且再次不能处理List

那么,有人可以帮助我们了解如何处理JdbcBatchItemWriter 中的列表列表吗?

【问题讨论】:

    标签: java spring-batch


    【解决方案1】:

    通常,设计模式是:

    Reader -> reads something, returns ReadItem
    Processor -> ingests ReadItem, returns ProcessedItem
    Writer -> ingests List<ProcessedItem>
    

    如果您的处理器返回 List&lt;Object&gt;,那么您需要您的 Writer 期待 List&lt;List&lt;Object&gt;&gt;

    您可以通过将您的 JdbcBatchItemWriter 包装为 ItemWriter 中的委托来做到这一点,如下所示:

    public class ListUnpackingItemWriter<T> implements ItemWriter<List<T>>, ItemStream, InitializingBean {
    
        private ItemWriter<T> delegate;
    
        @Override
        public void write(final List<? extends List<T>> lists) throws Exception {
            final List<T> consolidatedList = new ArrayList<>();
            for (final List<T> list : lists) {
                consolidatedList.addAll(list);
            }
            delegate.write(consolidatedList);
        }
    
        @Override
        public void afterPropertiesSet() {
            Assert.notNull(delegate, "You must set a delegate!");
        }
    
        @Override
        public void open(ExecutionContext executionContext) {
            if (delegate instanceof ItemStream) {
                ((ItemStream) delegate).open(executionContext);
            }
        }
    
        @Override
        public void update(ExecutionContext executionContext) {
            if (delegate instanceof ItemStream) {
                ((ItemStream) delegate).update(executionContext);
            }
        }
    
        @Override
        public void close() {
            if (delegate instanceof ItemStream) {
                ((ItemStream) delegate).close();
            }
        }
    
        public void setDelegate(ItemWriter<T> delegate) {
            this.delegate = delegate;
        }
    
    }
    

    【讨论】:

    • 建议了优秀的解决方案。我们计划通过实现forum.spring.io/forum/spring-projects/batch/… 来做一些更复杂的事情;但是您的解决方案足够通用。在后者中,我们需要做很多工作。测试它也会变得很麻烦。
    • 非常好的代码格式,你有可用的模板吗?
    • 建立一个列表并执行一次编写器可能更有效。
    • @Dean Clark:我在 delegate.write(consolidatedList) 处遇到空指针异常;
    • @yuva 你确定你设置了一个代表吗?这是该类的基本版本。实际上,它还应该实现 InitializingBean 并声明已提供委托编写器。
    【解决方案2】:
    public class ListUnpackingItemWriter<T> implements FlatFileItemWriter<List<T>>, ItemStream, InitializingBean {
    
        @Override
        public void afterPropertiesSet() {
            setLineAggregator(item -> String.join("\n", item.stream().map(T::toString).collect(Collectors.toList())));
        }
    
    }
    

    刚刚在上述解决方案中添加了一个自定义行聚合器,这有助于使用FlatFileItemWriter&lt;List&lt;T&gt;&gt; 将内容写入文件。您可以将T 替换为实际的类名,以避免在调用toString() 方法时出现编译错误。

    【讨论】:

    • ItemWriter 中没有 setLineAggregator 方法。这可能应该在底层委托编写器上调用。
    • 正确,setLineAggregator() 方法在 ItemWriter 中不存在,而在 FlatFileItemWriter 中存在。
    猜你喜欢
    • 2018-12-22
    • 2021-07-15
    • 1970-01-01
    • 2014-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多