【问题标题】:how to read csv columns in different order in spring batch with spring boot如何使用 Spring Boot 在 Spring Batch 中以不同顺序读取 csv 列
【发布时间】:2019-09-04 06:25:09
【问题描述】:

我正在创建一个读取 csv 文件并存储在 db 中的 spring 批处理应用程序。

只有当我按顺序设置列名时,我才能读取它并存储在数据库中。

当我更改 csv 文件中的顺序时它不起作用。

我的目标:

我的目标是即使列名不按顺序读取文件并存储在数据库中。

我的 CSV 文件如下所示:

id,name
1,xyz

上述订单按预期工作。但是如果像下面这样改变顺序,它就不起作用了。我该如何解决?

name,id
xyz,1

我的批量配置:

@Configuration
@EnableBatchProcessing
public class SpringBatchConfiguration {


    @Bean
    public Job job(JobBuilderFactory jobBuilderFactory,StepBuilderFactory stepBuilderFactory,
            ItemReader<BatchProcessEntity> itemReader,ItemWriter<BatchProcessEntity> itemWriter,ItemProcessor<BatchProcessEntity,BatchProcessEntity> itemProcessor) {

        Step step = stepBuilderFactory.get("Loading-file")
                    .<BatchProcessEntity,BatchProcessEntity>chunk(100)
                    .reader(itemReader)
                    .processor(itemProcessor)
                    .writer(itemWriter)
                    .build();

        Job job=jobBuilderFactory.get("Csv")
                .incrementer(new RunIdIncrementer())
                .start(step).build();

        return job;

    }

    @Bean
    public FlatFileItemReader<BatchProcessEntity> flatFileItemReader(@Value("${input}") Resource resource) {

        FlatFileItemReader<BatchProcessEntity> flatFileItemReader=new FlatFileItemReader<>();

        flatFileItemReader.setResource(resource);
        flatFileItemReader.setName("Loading Csv File");
        flatFileItemReader.setLinesToSkip(1);
        flatFileItemReader.setLineMapper(lineMapper());

        return flatFileItemReader;

    }

    @Bean
    public LineMapper<BatchProcessEntity> lineMapper() {

        DefaultLineMapper<BatchProcessEntity> defLineMapper=new DefaultLineMapper<>();

        DelimitedLineTokenizer delimitedLineTokenizer=new DelimitedLineTokenizer();
        delimitedLineTokenizer.setDelimiter(",");
        delimitedLineTokenizer.setStrict(true);
        delimitedLineTokenizer.setNames(new String[] {"id","name"});


        BeanWrapperFieldSetMapper<BatchProcessEntity> beanWrapperFieldSetMapper=new BeanWrapperFieldSetMapper<>();
        beanWrapperFieldSetMapper.setTargetType(BatchProcessEntity.class);


        defLineMapper.setLineTokenizer(delimitedLineTokenizer);
        defLineMapper.setFieldSetMapper(beanWrapperFieldSetMapper);

        return defLineMapper;
    }
}

我的实体:

@Entity
@Table(name="springbatchprocess")
@Data
public class BatchProcessEntity {

@Id
Integer id;

@Column(name="name")
String eName;

@Column(name="address")
String eAddress;

@Column(name="salary")
String eSalary;

@Column(name="dept")
String eDept;

@Column(name="status")
Integer eStatus;

@Column(name="date")
Date date;

}

只有当我按照代码中定义的顺序设置列时,上面的代码才能正常工作。当我更改订单时,它不起作用?

我该如何解决?

【问题讨论】:

  • 如果更改列顺序,则需要相应地更新线映射器。如果你想要一些动态的东西,你会创建一个自定义线映射器。

标签: java spring spring-boot spring-batch


【解决方案1】:

您需要编写一个自定义映射器来执行此操作。本教程中提供了一个示例:

https://www.baeldung.com/introduction-to-spring-batch

应该是这样的:

public class BatchProcessFieldSetMapper implements FieldSetMapper<BatchProcessEntity> {

    public BatchProcessEntity mapFieldSet(FieldSet fieldSet) throws BindException {

        BatchProcessEntity batchProcessEntity = new BatchProcessEntity();

        batchProcessEntity.setEAddress(fieldSet.readString("address"));

        //...etc

        return batchProcessEntity;
    }
}

【讨论】:

  • 这不起作用。 lineTokenizer 仍将遵循您在 lineTokenizer.setName() 中设置的顺序。因此,当调用 FieldSetMapper 时,标记器中的值将已经按照您在 setNames() 中设置的顺序排列,从而产生错误的结果。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-05-12
  • 2021-07-23
  • 2020-05-03
  • 2017-06-29
  • 1970-01-01
  • 2022-11-11
  • 2018-07-10
相关资源
最近更新 更多