【问题标题】:Spring batch FlatFileItemWriter write as csv from ObjectSpring批处理FlatFileItemWriter从Object写为csv
【发布时间】:2020-12-31 19:14:19
【问题描述】:

我正在使用 Spring 批处理,并且有一个 ItemWriter,如下所示:

public class MyItemWriter implements ItemWriter<Fixing> {

    private final FlatFileItemWriter<Fixing> writer;
    private final FileSystemResource resource;

    public MyItemWriter () {
        this.writer = new FlatFileItemWriter<>();
        this.resource = new FileSystemResource("target/output-teste.txt");
    }


    @Override
    public void write(List<? extends Fixing> items) throws Exception {

        this.writer.setResource(new FileSystemResource(resource.getFile()));
        this.writer.setLineAggregator(new PassThroughLineAggregator<>());
        this.writer.afterPropertiesSet();
        this.writer.open(new ExecutionContext());
        this.writer.write(items);
    }

    @AfterWrite
    private void close() {
        this.writer.close();
    }
}

当我运行我的春季批处理作业时,项目被写入文件:

Fixing{id='123456', source='TEST', startDate=null, endDate=null}
Fixing{id='1234567', source='TEST', startDate=null, endDate=null}
Fixing{id='1234568', source='TEST', startDate=null, endDate=null}

1/ 我怎样才能只写入数据,以便值以逗号分隔,并且在它为空的地方,它不被写入。所以目标文件应该是这样的:

123456,TEST
1234567,TEST
1234568,TEST

2/ 其次,我遇到了一个问题,只有当我退出 Spring Boot 应用程序时,我才能看到文件被创建。我想要的是,一旦它处理完所有项目并写入,文件就可以在不关闭 Spring Boot 应用程序的情况下使用。

【问题讨论】:

    标签: java spring spring-boot spring-batch


    【解决方案1】:

    有多个选项可以写入 csv 文件。关于第二个问题 writer flush 将解决问题。

    1. https://howtodoinjava.com/spring-batch/flatfileitemwriter-write-to-csv-file/
    1. 我们更喜欢将 OpenCSV 与 Spring Batch 一起使用,因为我们正在获得更快的速度和对大文件示例的控制,如下所示:sn-p

      class DocumentWriter implements ItemWriter<BaseDTO>, Closeable {
      
             private static final Logger LOG = LoggerFactory.getLogger(StatementWriter.class);
      
             private  ColumnPositionMappingStrategy<Statement> strategy ;
      
             private static final String[] columns = new String[] { "csvcolumn1", "csvcolumn2", "csvcolumn3",
      
                                          "csvcolumn4", "csvcolumn5", "csvcolumn6", "csvcolumn7"};
      
             private BufferedWriter writer;
             private StatefulBeanToCsv<Statement> beanToCsv;
             public DocumentWriter() throws Exception {
      
                            strategy = new ColumnPositionMappingStrategy<Statement>();
      
                           strategy.setType(Statement.class);
      
                            strategy.setColumnMapping(columns);
      
                            filename = env.getProperty("globys.statement.cdf.path")+"-"+processCount+".dat";
      
                            File cdf = new File(filename);
      
                     if(cdf.exists()){
      
                         writer = Files.newBufferedWriter(Paths.get(filename), StandardCharsets.UTF_8,StandardOpenOption.APPEND);
      
                     }else{
      
                         writer = Files.newBufferedWriter(Paths.get(filename), StandardCharsets.UTF_8,StandardOpenOption.CREATE_NEW);
      
                     }
      
                     beanToCsv = new StatefulBeanToCsvBuilder<Statement>(writer).withQuotechar(CSVWriter.NO_QUOTE_CHARACTER)
      
                             .withMappingStrategy(strategy).withSeparator(',').build();
      
             }
      
             @Override
      
             public void write(List<? extends BaseDTO> items) throws Exception {
      
                            List<Statement> settlementList = new ArrayList<Statement>();
      
                            for (int i = 0; i < items.size(); i++) {
      
                                          BaseDTO baseDTO = items.get(i);
      
                                          settlementList.addAll(baseDTO.getStatementList());
      
                            }
      
                            beanToCsv.write(settlementList);
      
                            writer.flush();
      
             }
      
             @PreDestroy
      
             @Override
      
             public void close() throws IOException {
      
                            writer.close();
      
             }
      

      }

    【讨论】:

      【解决方案2】:

      由于您使用 PassThroughLineAggregator 执行 item.toString() 来编写对象,因此覆盖扩展 Fixing.java 的类的 toString() 函数应该可以解决它。

      【讨论】:

        【解决方案3】:

        1/ 我怎样才能只写数据,以便值以逗号分隔,如果为空,则不写。

        您需要提供一个自定义的LineAggregator 过滤掉null 字段。

        2/ 其次,我遇到了一个问题,只有当我退出 Spring Boot 应用程序时,我才能看到文件被创建

        这可能是因为您在不正确的write 方法中调用了this.writer.open。您需要让您的项目编写器实现ItemStream 并分别在ItemStream#openItemStream#close 中调用this.writer.open 和这个this.writer.close

        【讨论】:

        • 对于 1/ 我使用了 NullSafeBeanWrapperFieldExtractor。对于 2/,我进行了更改以实现 ItemStream,但在我开始在我的 writer 上使用 @Configuration 之前问题已经解决,而以前不是这样,我正在我的作业配置中创建 bean
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-30
        相关资源
        最近更新 更多