我有一个输入数据库MyInputEntity,可以这样说:
id, name, someCode
1,john,code_abc
2,jack,code_xyz
此文件由spring批处理作业处理,它的每一行都会在这2个表中创建一行:
OutPerson:
id
name
OutCode:
code
配置为:
@Bean
public Step step3_readDBWriteDB(OutCodeRepository outCodeRepository) {
return stepBuilderFactory.get("step3_readDBWriteDB")
.<MyInputEntity, OutPerson>chunk(100)
.reader(myReader())
.processor(new MyItemProcessor(outCodeRepository))
.writer(myWriter()).build();
}
itemProcessor是这样的:
@Override
public OutPerson process(MyInputEntity myInput) {
// creation of Person
OutPerson outPerson = MyMapper.convert(myInput);
// Create and save outCode
OutCode outCode = new outCode(myInput.getCode());
OutCodeRepository.save(outCode)
return outPerson;
}
这里的问题是,Person用100的块进行处理。因此代码保存在每一行上,而person每100行保存一次。
我认为这里有问题,应该以不同的方式进行,但是我不知道怎么办?我应该为“代码”创建另一个处理器吗?在这种情况下(对于每一行,在多表中创建)的最佳做法是什么?
答案 0 :(得分:2)
我建议将所有写作逻辑都保留在作家中,因为这就是作家的目的。 我认为最好的方法是在编写器中一起编写代码和人员(假设这是同一数据库,因此它们将在同一事务中编写)。
但是请注意,它们将以大块= chunk(100)
这样,当一次写入数据库失败并出现任何错误时,您还可以从spring批处理的回退机制中受益。在目前的情况下,我认为您需要自己解决。
答案 1 :(得分:1)
我建议创建一个名为MyOutputEntity
的包装器类,该包装器封装OutPerson
和OutCode
。此类将是处理器的输出和编写器的输入。编写者将在同一事务中将人员和代码一起插入(因此在失败的情况下您的数据是一致的)。例如:
class MyOutputEntity {
private OutPerson outPerson;
private OutCode outCode;
// getters and setters
}
public ItemProcessor<MyInputEntity, MyOutputEntity> itemProcessor() {
return myInputEntity -> {
// create Person
OutPerson outPerson = MyMapper.convert(myInputEntity);
// Create outCode
OutCode outCode = new outCode(myInputEntity.getCode());
MyOutputEntity myOutputEntity = new MyOutputEntity();
myOutputEntity.setOutPerson(outPerson);
myOutputEntity.setOutCode(outCode);
return myOutputEntity;
};
}
public ItemWriter<MyOutputEntity> itemWriter() {
return items -> {
for (MyOutputEntity outputEntity : items) {
outPersonRepository.save(outputEntity.getOutPerson());
outCodeRepository.save(outputEntity.getOutCode());
}
};
}
希望这会有所帮助。