我正在使用Spring Batch从CSV文件读取数据,然后将其保存到数据库中。到目前为止,一切都很好,只不过我的输入文件包含混合数据(多个表的多个列)。

我创建了一个类CsvFileLine,它将包含整个文件行,并实现了接口ItemReader<CsvFileLine>,然后实现了接口ItemProcessor<List<CsvFileLine>, ProcessorResult>,我将向其传递CsvFileLine的列表,并返回一个类型为object的对象。我也创建的ProcessorResult包含3个ArrayList<>,分别是ClassAClassBClassC

我现在的问题是,当我需要实现接口ItemWriter<ProcessorResult>时,方法write(List<? extends T> items)需要一个扩展了其他类的项目列表,而我打算传递一个对象,该对象是ProcessorResult,其中包含4个具有必要数据的ArrayLists。

有人可以建议我如何处理此案吗?是否有解决方法只能传递1个参数?

最佳答案

感谢您的澄清。如果我理解正确,您就是说文件中的每一行都包含一个ClassAClassBClassC的实例。在本示例中,我将假定这样做,但是即使关系有所不同,解决方案也将相似。

设置Spring Batch作业的关键是考虑构成“项目”的内容以及您要发生的事情。您还需要了解框架如何将每个接口的输出作为下一个的输入。 (Spring具有很好的documentation)。 ItemReader的返回类型作为单例传递给ItemProcessor。因此,在您的情况下,ItemProcessor实际上应该是ItemProcessor<CsvFileLine, ProcessorResult>而不是您拥有的ItemProcessor<List<CsvFileLine>, ProcessorResult>。从ItemProcessorItemWriter的切换有些棘手。 ItemWriter实现应采用List返回类型的ItemProcessorItemWriter需要一个List,因为Spring Batch将ItemProcessor的输出一起分组为事务。就您而言,您可以使用ItemWriter<List<ProcessorResult>>

在此基础上,我们可以更改ProcessorResult的结构,从而使编写者易于实现。它不包含文件中所有数据的ProcessorResult,而是仅包含一行的数据:

public class ProcessorResult {
    private ClassA classA;
    private ClassB classB;
    private ClassC classC;
    // Constructor and getters omitted for brevity
}


ItemProcessor取一个CsvFileLine并将其转换为一个ProcessorResult

public class ExampleProcessor implements ItemProcessor<CsvFileLine, ProcessorResult> {

  public ProcessorResult process(CsvFileLine line){
    // mapping into ProcessorResult goes here
  }


ItemWriter接受其中的List,需要将它们保存到数据库中。它可能看起来像这样:

public class ExampleItemWriter implements ItemWriter<List<ProcessorResult>{

  private ClassADao classADao;
  private ClassBDao classBDao;
  private ClassCDao classCDao;

  public void write(List<? extends ProcessorResult> items){
     for(ProcessorResult result : items){
        classADao.save(result.getClassA());
        classBDao.save(result.getClassB());
        classCDao.save(result.getClassC());
     }
  }
}


请记住,传递给ListItemWriter中的每个元素都映射回ItemReader中的单个项目。通常,这也将是文件中的一行。要使用Spring Batch,您必须确保ItemReader的返回类型是ItemProcessor的输入类型。同时,对ItemWriter的输入是List返回的类型的ItemProcessor。您在此处拥有的读取器,处理器和写入器不遵循该模式,因此框架将无法使用它们。进行一些小改动,即可使用您在框架中编写的代码。

最后,我会指出,您可能根本不需要ItemProcessor就能做到这一点。您可以只具有ItemReader<ProcessorResult>ItemWriter<ProcessorResult>并在ItemReader中进行映射。因此,您可以将逻辑从当前的ItemProcessor移至LineMapper<ProcessorResult>。然后在FlatFileItemReader中使用它,然后一切都直接从读者传递到作家。这超出了您的问题范围,我更喜欢XML配置,因此我将其保留。

08-16 14:34