我正在使用Spring Batch从CSV文件读取数据,然后将其保存到数据库中。到目前为止,一切都很好,只不过我的输入文件包含混合数据(多个表的多个列)。
我创建了一个类CsvFileLine
,它将包含整个文件行,并实现了接口ItemReader<CsvFileLine>
,然后实现了接口ItemProcessor<List<CsvFileLine>, ProcessorResult>
,我将向其传递CsvFileLine
的列表,并返回一个类型为object的对象。我也创建的ProcessorResult
包含3个ArrayList<>
,分别是ClassA
,ClassB
和ClassC
。
我现在的问题是,当我需要实现接口ItemWriter<ProcessorResult>
时,方法write(List<? extends T> items)
需要一个扩展了其他类的项目列表,而我打算传递一个对象,该对象是ProcessorResult,其中包含4个具有必要数据的ArrayLists。
有人可以建议我如何处理此案吗?是否有解决方法只能传递1个参数?
最佳答案
感谢您的澄清。如果我理解正确,您就是说文件中的每一行都包含一个ClassA
,ClassB
和ClassC
的实例。在本示例中,我将假定这样做,但是即使关系有所不同,解决方案也将相似。
设置Spring Batch作业的关键是考虑构成“项目”的内容以及您要发生的事情。您还需要了解框架如何将每个接口的输出作为下一个的输入。 (Spring具有很好的documentation)。 ItemReader
的返回类型作为单例传递给ItemProcessor
。因此,在您的情况下,ItemProcessor
实际上应该是ItemProcessor<CsvFileLine, ProcessorResult>
而不是您拥有的ItemProcessor<List<CsvFileLine>, ProcessorResult>
。从ItemProcessor
到ItemWriter
的切换有些棘手。 ItemWriter
实现应采用List
返回类型的ItemProcessor
。 ItemWriter
需要一个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());
}
}
}
请记住,传递给
List
的ItemWriter
中的每个元素都映射回ItemReader
中的单个项目。通常,这也将是文件中的一行。要使用Spring Batch,您必须确保ItemReader
的返回类型是ItemProcessor
的输入类型。同时,对ItemWriter
的输入是List
返回的类型的ItemProcessor
。您在此处拥有的读取器,处理器和写入器不遵循该模式,因此框架将无法使用它们。进行一些小改动,即可使用您在框架中编写的代码。最后,我会指出,您可能根本不需要
ItemProcessor
就能做到这一点。您可以只具有ItemReader<ProcessorResult>
和ItemWriter<ProcessorResult>
并在ItemReader
中进行映射。因此,您可以将逻辑从当前的ItemProcessor
移至LineMapper<ProcessorResult>
。然后在FlatFileItemReader
中使用它,然后一切都直接从读者传递到作家。这超出了您的问题范围,我更喜欢XML配置,因此我将其保留。