Java 传递单个参数而不是ItemWriter接口的list to Write()方法

Java 传递单个参数而不是ItemWriter接口的list to Write()方法,java,spring,spring-batch,batch-processing,Java,Spring,Spring Batch,Batch Processing,我使用SpringBatch从CSV文件中读取数据,然后将其保存到数据库中。到目前为止,一切都很好,除了我的输入文件包含多个表的多个列的混合数据 我创建了一个类CsvFileLine,它将包含一整行文件,并实现了interface ItemReader,然后实现了interface ItemProcessor,我将向其传递CsvFileLine列表,它将返回我创建的ProcessorResult类型的对象,并包含ClassA、ClassB和ClassC的3个ArrayList 我现在的问题是,当

我使用SpringBatch从CSV文件中读取数据,然后将其保存到数据库中。到目前为止,一切都很好,除了我的输入文件包含多个表的多个列的混合数据

我创建了一个类CsvFileLine,它将包含一整行文件,并实现了interface ItemReader,然后实现了interface ItemProcessor,我将向其传递CsvFileLine列表,它将返回我创建的ProcessorResult类型的对象,并包含ClassA、ClassB和ClassC的3个ArrayList

我现在的问题是,当我需要实现接口ItemWriter方法writeList时,因为您选择了使用Spring批处理及其ItemWriter,所以您需要明确知道域对象如何映射到项

假设ProcessorResult构成单个项,只需使用大小为1的列表调用ItemWriter.write

标准Java API为您提供Collections.singletonList来方便地执行此操作

 itemWriter.write(Collections.singletonList(processorResult));

谢谢你的澄清。如果我理解正确的话,您的意思是文件中的每一行都包含ClassA、ClassB和ClassC的一个实例。对于这个例子,我将假设,但即使关系不同,解决方案也会相似

设置Spring批处理作业的关键是考虑项目的构成以及您希望对其发生什么。您还需要了解框架如何将每个接口的输出作为下一个接口的输入传递。春天有好天气。ItemReader的返回类型作为单例传递给ItemProcessor。因此,在您的例子中,ItemProcessor实际上应该是ItemProcessor,而不是您拥有的ItemProcessor。从ItemProcessor到ItemWriter的切换有点棘手。ItemWriter实现应该从ItemProcessor获取返回类型的列表。ItemWriter获取一个列表,因为Spring批处理将ItemProcessor输出一起分组到事务中。在您的情况下,您可以使用ItemWriter

在这个基础上,我们可以改变处理结果的结构,使作者易于实现。与包含文件中所有数据的ProcessorResult不同,它只包含一行数据:

public class ProcessorResult {
    private ClassA classA;
    private ClassB classB;
    private ClassC classC;
    // Constructor and getters omitted for brevity
}
ItemProcessor获取一个CsvFileLine并将其转换为一个ProcessorResult:

请记住,传递给ItemWriter的列表中的每个元素都映射回ItemReader中的单个项。通常,这也是文件中的一行。要使用SpringBatch,必须确保ItemReader的返回类型是ItemProcessor的输入类型。同时,ItemWriter的输入是ItemProcessor返回的类型列表。您在这里拥有的读卡器、处理器和编写器不遵循该模式,框架将无法使用它们。一些小的更改应该允许您使用在框架中编写的代码


最后,我要指出的是,您可能根本不需要ItemProcessor就可以做到这一点。您可以使用ItemReader和ItemWriter,并在ItemReader中进行映射。因此,您可以将逻辑从当前的ItemProcessor移到LineMapper中。然后在FlatFileItemReader中使用它,然后所有内容都直接从读卡器传递到写卡器。这超出了您的问题范围,我更喜欢XML配置,所以我就不谈了。

实际上,我的ProcessorResult包含3个ArrayList:ProcessorResult.ListClassA、ProcessorResult.ListClassB和ProcessorResult.ListClassC。每个列表包含多个对象。现在我正在考虑为每个ArrayList创建一个专用的编写器,比如ItemWriter…我不知道您的域,但您可能应该创建ClassA,ClassB,ClassC实现了一个公共接口,因此您可以对它们进行多态处理。对于ItemProcessor,每次我都返回一个ClassX列表,而不是返回一个封装所有类的对象?1。为什么不使用标准Spring批处理组件来读取CSV FlatFileItemReader等?2.处理多个项目类型和ItemWriter抽象有几个不同的选项。像ClassifierCompositeItemWriter这样的组合是最常见的方法。CSV文件中的一行与您最终想要写入数据库的内容有什么关系?文件中的一行是否与数据库中的一个insert/update完全对应,即ClassA、ClassB或ClassC中的一个?一个文件行可以表示其中一个类的多个实例吗?我认为您在这里使用的是Spring Batch框架,但如果不知道实际的最终目标,我无法提供许多有用的建议。@MichaelMinella我是Spring Batch的新手,我正在遵循一个我认为是公司标准的常见示例。关于如何使用FlatFileItemReader而不进行纯XML注释,您有什么好的例子吗?@mymarkers实际上数据库中的表与我的POJO ClassA、ClassB和
ClassC和文件的一行包含添加到每个实例上所需的所有数据。我希望这是清楚的:非常感谢你的帮助。我将按照您告诉我的模式重写代码,并尝试应用业务逻辑。实际上,我考虑的是如何在不同实体之间建立链接,因为例如ClassA有一个类型为List listClassB的属性,classC也是这样。。
public class ExampleProcessor implements ItemProcessor<CsvFileLine, ProcessorResult> {

  public ProcessorResult process(CsvFileLine line){
    // mapping into ProcessorResult goes here
  }
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());
     }
  }
}