我使用Spring Batch从CSV文件中读取数据,然后将其保存到数据库中。到目前为止一切都很好,除了我的输入文件包含混合数据(多个表的多列)。
我创建了一个类CsvFileLine
,它将包含整行文件,并实现了接口ItemReader<CsvFileLine>
,然后实现了接口ItemProcessor<List<CsvFileLine>, ProcessorResult>
,我将向其传递{{ {1}}它返回我创建的CsvFileLine
类型的对象,其中包含3 ProcessorResult
ArrayList<>
,ClassA
和ClassB
。
我现在的问题是,当我需要实现接口ClassC
时,方法ItemWriter<ProcessorResult>
需要一个扩展其他类的项目列表,而我打算传递一个包含该对象的ProcessorResult对象4个包含必要数据的ArrayLists。
有谁能建议我如何处理这个案子?有没有工作只传递1个参数?
答案 0 :(得分: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
的{{1}}中的每个元素都会映射回ItemWriter
中的单个项目。通常,这也是文件中的一行。要使用Spring Batch,您必须确保ItemReader
的返回类型是ItemReader
的输入类型。同时,ItemProcessor
的输入是ItemWriter
返回的List
类型的输入。您在这里的阅读器,处理器和编写器不遵循该模式,框架将无法使用它们。一些小的改动应该允许你使用你在框架中编写的代码。
最后,我会注意到你可能在没有ItemProcessor
的情况下这样做。您可以拥有ItemProcessor
和ItemReader<ProcessorResult>
并在ItemWriter<ProcessorResult>
中进行映射。因此,您将逻辑从当前ItemReader
转移到ItemProcessor
。然后在LineMapper<ProcessorResult>
中使用它,然后一切都直接从读者传递到作者。这超出了你的问题的范围,我更喜欢XML配置,所以我会留下它。
答案 1 :(得分:0)
由于您已选择以使用Spring Batch及其ItemWriter
,因此您需要明确了解域对象如何映射到“项目”。
假设您的ProcessorResult
构成一个“项目”,只需使用大小为1的列表调用ItemWriter.write()
。
标准Java API为您Collections.singletonList()
提供了方便的功能。
itemWriter.write(Collections.singletonList(processorResult));