Spring批处理中的多个项目编写器

Posted

技术标签:

【中文标题】Spring批处理中的多个项目编写器【英文标题】:Multiple itemwriters in Spring batch 【发布时间】:2013-09-25 18:40:17 【问题描述】:

我目前正在编写一个 Spring 批处理,我正在读取大量数据,对其进行处理,然后我希望将这些数据传递给 2 个写入器。一位作家将简单地更新数据库,而第二位作家将写入一个 csv 文件。

我打算编写自己的自定义编写器,并在 customItemWriter 中注入两个 itemWriter,并在 customItemWriter 的 write 方法中调用两个项目编写器的 write 方法。这种方法正确吗?是否有任何可用的 ItemWriter 实现满足我的要求?

提前致谢

【问题讨论】:

【参考方案1】:

您可以使用 Spring 的 CompositeItemWriter 并将您的所有作者委托给它。 这是configuration example。

【讨论】:

这个例子真的很有帮助。 嗨 Pratik - 你能分享示例代码吗?我已经筋疲力尽地无法解决这个问题。 这条线断了:-( @Andy 这是新网址:github.com/spring-projects/spring-batch/blob/master/…。我更新了答案【参考方案2】:

您不一定必须像示例中那样使用 xml。如果您的其余代码使用注释,您可以简单地执行以下操作。

public ItemWriter<T> writerOne()
    ItemWriter<T> writer = new ItemWriter<T>();
    //your logic here
    return writer;


public ItemWriter<T> writerTwo()
    ItemWriter<T> writer = new ItemWriter<T>();
    //your logic here
    return writer;


public CompositeItemWriter<T> compositeItemWriter()
    CompositeItemWriter writer = new CompositeItemWriter();
    writer.setDelegates(Arrays.asList(writerOne(),writerTwo()));
    return writer;

【讨论】:

【参考方案3】:

你是对的。 SB 很大程度上基于委托,因此使用CompositeItemWriter 是满足您需求的正确选择。

【讨论】:

你知道如何通过多线程编写器来实现这一点吗?【参考方案4】:

Java Config方式SpringBatch4

@Bean
    public Step step1() 
            return this.stepBuilderFactory.get("step1")
                                    .<String, String>chunk(2)
                                    .reader(itemReader())
                                    .writer(compositeItemWriter())
                                    .stream(fileItemWriter1())
                                    .stream(fileItemWriter2())
                                    .build();
    

    /**
     * In Spring Batch 4, the CompositeItemWriter implements ItemStream so this isn't
     * necessary, but used for an example.
     */
    @Bean
    public CompositeItemWriter compositeItemWriter() 
            List<ItemWriter> writers = new ArrayList<>(2);
            writers.add(fileItemWriter1());
            writers.add(fileItemWriter2());

            CompositeItemWriter itemWriter = new CompositeItemWriter();

            itemWriter.setDelegates(writers);

            return itemWriter;
    

【讨论】:

这取自 spring 参考文档:docs.spring.io/spring-batch/docs/current/reference/html/…【参考方案5】:

根据您的需要,另一种选择是扩展 Writer 类并在其中添加功能。例如,我有一个项目,我在其中扩展 HibernateItemWriter,然后覆盖 write(List items)。然后,我将正在写入的对象与 sessionFactory 一起发送到 Writer 的 doWrite 方法:doWrite(sessionFactory, filteredRecords)。

所以在上面的例子中,我可以在我的扩展类中写入 csv 文件,然后 HibernateItemWriter 会写入数据库。显然,这对于本示例可能并不理想,但对于某些场景,这是一个不错的选择。

【讨论】:

【参考方案6】:

这是一个可能的解决方案。 Composite Writer 中的两个 writer。

    @Bean
public JdbcBatchItemWriter<XPTO> writer(DataSource dataSource)         
    return new JdbcBatchItemWriterBuilder<XPTO>()
            .itemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>())
            .sql("UPDATE xxxx")
            .dataSource(dataSource)             
            .build();


@Bean
public JdbcBatchItemWriter<XPTO> writer2(DataSource dataSource)            
    return new JdbcBatchItemWriterBuilder<XPTO>()
            .itemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>())
            .sql("UPDATE yyyyy")
            .dataSource(dataSource)             
            .build();


@Bean
public CompositeItemWriter<XPTO> compositeItemWriter(DataSource dataSource) 
    CompositeItemWriter<XPTO> compositeItemWriter = new CompositeItemWriter<>();
    compositeItemWriter.setDelegates(Arrays.asList( writer(dataSource), writer2(dataSource)));
    return compositeItemWriter;


@Bean
protected Step step1(DataSource datasource) 
    
    return this.stepBuilderFactory.get("step1").
            <XPTO, XPTO>chunk(1).
            reader(reader()).
            processor(processor()).             
            writer(compositeItemWriter(datasource)).
            build();

   

【讨论】:

根据 qtn,一个应该写入 DB,而另一个写入 CSV。但是您的示例仅显示更新数据库 我的例子的更新只是展示了如何更新两个不同的表。可以是数据库和 CSV 吗?当然!

以上是关于Spring批处理中的多个项目编写器的主要内容,如果未能解决你的问题,请参考以下文章

如果写入元素发生异常,如何正确处理 Spring Batch 步骤编写器异常以便继续处理其他元素?

Spring Boot Spring Batch:没有 Spring 批处理元数据表的多个 DataSource

Spring MockRestServiceServer 处理多个异步请求

如何在 Spring 身份验证管理器之前执行自定义处理程序

OpenShift 中的 Spring 批处理 JDBCPagingItemReader、ThreadPoolTask​​Executor 和多个 pod

修改Spring源码对Web项目进行加密