如何读取平面文件并在读取每一定量的记录时打印一行 - Spring Batch

时间:2018-03-08 14:27:23

标签: java spring spring-batch batch-processing

Hello Spring Batch社区!

我正在读一个平面文件,它有一个标题并映射到headerPOJO,还有一个正文(百万条记录)映射到bodyPOJO。

输入文件:

01.01.2017|SUBDCOBR|12:21:23|01/12/2016|31/12/2016
01.01.2017|12345678231234|0002342434|BORGIA RUBEN|27-32548987-9|FA|A|2062-
00010443/444/445|142,12|30/08/2017|142,01
01.01.2017|12345673201234|2342434|ALVAREZ ESTHER|27-32533987-9|FA|A|2062-
00010443/444/445|142,12|30/08/2017|142,02
01.01.2017|12345673201234|0002342434|LOPEZ LUCRECIA|27-32553387-9|FA|A|2062-
00010443/444/445|142,12|30/08/2017|142,12
01.01.2017|12345672301234|0002342434|SILVA JESUS|27-32558657-9|NC|A|2062-
00010443|142,12|30/08/2017|142,12
.
.   
.

具体来说,我需要打印一个格式化的平面文件,其结构如下:

HEADER (8 customed lines, using data from HEADER input)
DETAILS (17 records from the body)
line break
SAME HEADER
DETAILS (next 17 records from the body)
line break
...
...  
...
REPEAT until EOF

我似乎无法理解如何从主体的FlatFileItemReader实现,并告诉每17条读取行打印标题。我尝试做一个stepHeader和一个stepBody,并生成ExitStatus ..但它总是打印相同的17条第一条记录,或者只是循环而且永远不会结束。请帮忙!!

================== 更新 ==================

我所做的是......创建一个stepHeader和一个stepBody。他们每个人都有自己的读者,处理器(商业格式化器)和作家。

这项工作只有两个简单的步骤。

@Bean
public Job job() throws Exception {
    return jobBuilderFactory.get("job")
            .incrementer(new RunIdIncrementer())
            .listener(new JobListener())
            .start(stepHeader())
            .next(stepBody())
            .on("BACK TO STEPHEADER").to(stepHeader())
            .on("END").end().build()
            .build();
}

我读取的标题配置为MaxItemCount = 1,并将其映射到CabeceraFacturacion:

@Bean
public FlatFileItemReader<CabeceraFacturacion> readerCabecera() throws Exception{

FlatFileItemReader<CabeceraFacturacion> reader = new FlatFileItemReader<>();

reader.setLinesToSkip(0);
reader.setMaxItemCount(1);
reader.setResource(new ClassPathResource("/inputFiles/input.txt"));

DefaultLineMapper<CabeceraFacturacion> cabeceraLineMapper = new DefaultLineMapper<>();

DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer("|"); // en el default, la coma es el separador
tokenizer.setNames(new String[] {"printDate", "reportIdentifier", "tituloReporte", "fechaDesde", "fechaHasta"});

cabeceraLineMapper.setLineTokenizer(tokenizer);
cabeceraLineMapper.setFieldSetMapper(new CabeceraFieldSetMapper());
cabeceraLineMapper.afterPropertiesSet();

reader.setLineMapper(cabeceraLineMapper);

return reader;
}

我用这种方式读取它,跳过第一行,并将其映射到DetalleFacturacion:

@Bean     public FlatFileItemReader readerDetalleFacturacion(){

FlatFileItemReader<DetalleFacturacion> reader = new FlatFileItemReader<>();

reader.setLinesToSkip(1);
//reader.setMaxItemCount(17);
reader.setResource(new ClassPathResource("/inputFiles/input.txt"));

DefaultLineMapper<DetalleFacturacion> detalleLineMapper = new DefaultLineMapper<>();

DelimitedLineTokenizer tokenizerDet = new DelimitedLineTokenizer("|"); // en el default, la coma es el separador
tokenizerDet.setNames(new String[] {"fechaEmision", "tipoDocumento", "letra", "nroComprobante",  
                            "nroCliente", "razonSocial", "cuit", "montoNetoGP", "montoNetoG3",
                            "montoExento", "impuestos", "montoTotal"});



detalleLineMapper.setLineTokenizer(tokenizerDet);
detalleLineMapper.setFieldSetMapper(new DetalleFieldSetMapper());
detalleLineMapper.afterPropertiesSet();
reader.setLineMapper(detalleLineMapper);


return reader;
}   

我的步骤:

@Bean
public Step stepHeader() throws Exception {
   return stepBuilderFactory.get("stepHeader")
        .<CabeceraFacturacion, CabeceraFacturacion> chunk(17)
        .faultTolerant()
        .listener(new ChunkListener())
        .reader(readerCabecera())
        .writer(writerCabeceraFact())
        .allowStartIfComplete(true)
        .build();
}


@Bean
public Step stepBody() {
   return stepBuilderFactory.get("stepBody")
        .<DetalleFacturacion, DetalleFacturacion> chunk(17)
        .chunk(17)
        .faultTolerant()
        .listener(new ChunkListener())
        .reader(readerDetalleFacturacion())
        .writer(writerDetalleFact())
        .listener(new StepExecutionListener() {

            @Override
            public ExitStatus afterStep(StepExecution stepExecution) {
                if(stepExecution.getWriteCount()==17) {

                    return new ExitStatus("BACK TO STEPHEADER");                    
                };

//                      if(stepExecution.getReadCount()<17) {
//                          return new ExitStatus("END");                   

//                      }

                return null;
            }

            @Override
            public void beforeStep(StepExecution stepExecution) {


            }


        })
        .allowStartIfComplete(true)
        .build();
}

1)我不知道如何在文件结束前无限制地返回StepHeader。我尝试使用stepExecution.getWriteCount(17)..但我不确定这是正确的方法。

2)我不知道每次循环时如何读取17条不同的记录(我设法让它循环但它会反复写出相同的前17条记录,直到我手动停止工作。(我现在知道在Spring Batch进程中不建议使用循环)

3)如果有人对另一种方式有任何想法来实现我的目标,那将是非常受欢迎的。

4)有没有办法让决策者一直“听到”,并在满足某些条件的情况下发送订单打印标题或正文?

到目前为止,我所达到的最大值是阅读&amp;只写一次标题...并在下一步阅读&amp;写下17行身体。

0 个答案:

没有答案