35

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

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

提前致谢

4

6 回答 6

26

您可以使用 Spring 的CompositeItemWriter并将所有作者委托给它。
这是一个配置示例

于 2013-09-20T12:26:21.607 回答
15

您不必像示例那样使用 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;
}
于 2016-08-26T22:39:52.993 回答
4

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

于 2013-09-20T12:24:29.800 回答
2

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;
    }
于 2018-09-03T07:03:14.673 回答
0

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

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

于 2015-06-05T18:06:08.157 回答
0

这是一个可能的解决方案。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();

}   
于 2021-02-08T22:47:50.753 回答