Domain driven design DDD和批处理(例如使用Spring批处理)
我想将SpringBatch用于批处理应用程序。我已经有了一个按照DDD设计的域模型。我的问题是批处理(在我的例子中,使用SpringBatch)如何适合DDD 例如,我有一个聚合根A,它的一个子实体是实体B。A有一个包含一个或多个B的列表。当每一行对应于Bs列表上的操作(添加、删除…)时,批处理应用程序接收一个文件。在我的聚合根A中,每个操作都有一个方法(例如addB、delB…)。使用SpringBatch,我应该使用哪个ItemWriter?我认为JdbcBatchItemWriter并不合适,因为我应该只通过域处理数据。是否有关于批处理使用DDD的最佳实践Domain driven design DDD和批处理(例如使用Spring批处理),domain-driven-design,spring-batch,Domain Driven Design,Spring Batch,我想将SpringBatch用于批处理应用程序。我已经有了一个按照DDD设计的域模型。我的问题是批处理(在我的例子中,使用SpringBatch)如何适合DDD 例如,我有一个聚合根A,它的一个子实体是实体B。A有一个包含一个或多个B的列表。当每一行对应于Bs列表上的操作(添加、删除…)时,批处理应用程序接收一个文件。在我的聚合根A中,每个操作都有一个方法(例如addB、delB…)。使用SpringBatch,我应该使用哪个ItemWriter?我认为JdbcBatchItemWriter并不
谢谢我不想假装知道这方面的最佳实践是什么,但考虑到您的设计目标,我会这样做。假设我们有一个文件对象,即您的聚合,而不是A和B,它包含许多行:
class File {
public void addLine(Line l) {/* implementation here*/}
public void removeLine(Line l) {/* implementation here*/}
}
class Line {
}
让您的读卡器/处理器返回行操作,封装您的行(您刚刚阅读的行),以及您是否正在执行添加/删除/其他操作:
interface LineOperation {
public void execute(File file);
}
class DeleteOperation implements LineOperation {
private Line line;
private DeleteOperation(Line line) {
super();
this.line = line;
}
public void execute(File file) {
file.removeLine(line);
}
}
AddOperation的实现以及您可能需要的任何其他功能都留给您想象
接下来,我们将把LineOperations传递给编写器。编写器对聚合文件执行操作,然后使用FileRepository编写聚合
class LineOperationWriter implements ItemWriter<LineOperation>, StepExecutionListener {
@Autowired;
FileRepository fileRepo;
private Long fileId;
public void write(List<? extends LineOperation> items) throws Exception {
File file = fileRepo.find(fileId);
for (LineOperation lineOperation : items) {
lineOperation.execute(file);
}
fileRepo.persist(file);
}
@Override
public void beforeStep(StepExecution stepExecution) {
this.fileId = (Long) stepExecution.getJobExecution().getExecutionContext().get("fileId");
}
@Override
public ExitStatus afterStep(StepExecution stepExecution) {
return null;
}
}
类LineOperationWriter实现ItemWriter、StepExecutionListener{
@自动连线;
档案库档案库;
私有长文件ID;
public void write(List我不知道这方面的最佳实践是什么,但考虑到您的设计目标,我会这样做。假设我们有一个文件对象,即您的聚合,它包含许多行,而不是A和B:
class File {
public void addLine(Line l) {/* implementation here*/}
public void removeLine(Line l) {/* implementation here*/}
}
class Line {
}
让您的读卡器/处理器返回行操作,封装您的行(您刚刚阅读的行),以及您是否正在执行添加/删除/其他操作:
interface LineOperation {
public void execute(File file);
}
class DeleteOperation implements LineOperation {
private Line line;
private DeleteOperation(Line line) {
super();
this.line = line;
}
public void execute(File file) {
file.removeLine(line);
}
}
AddOperation的实现以及您可能需要的任何其他功能都留给您想象
接下来,我们将把行操作传递给编写器。编写器对聚合文件执行操作,然后使用FileRepository编写聚合
class LineOperationWriter implements ItemWriter<LineOperation>, StepExecutionListener {
@Autowired;
FileRepository fileRepo;
private Long fileId;
public void write(List<? extends LineOperation> items) throws Exception {
File file = fileRepo.find(fileId);
for (LineOperation lineOperation : items) {
lineOperation.execute(file);
}
fileRepo.persist(file);
}
@Override
public void beforeStep(StepExecution stepExecution) {
this.fileId = (Long) stepExecution.getJobExecution().getExecutionContext().get("fileId");
}
@Override
public ExitStatus afterStep(StepExecution stepExecution) {
return null;
}
}
类LineOperationWriter实现ItemWriter、StepExecutionListener{
@自动连线;
档案库档案库;
私有长文件ID;
公开无效写入(列表数据访问层使用的是什么?Spring Batch集成了几个现成的组件,并且可以使用ItemWriterAdapter轻松地调整其他组件。A是聚合根,因此我有一个存储库。我已经使用Hibernate实现了存储库。但是正如我所说的,我不认为我应该使用HibernateWriter,因为我不能使用它直接与数据库通信,我应该只与域模型通信。您的数据访问层使用的是什么?Spring Batch集成了几个现成的组件,并且可以使用ItemWriterAdapter轻松地调整其他组件。A是聚合根,因此我有一个存储库。我使用Hibernate实现了存储库。但是正如我所说的,我不认为我应该使用HibernateWriter,因为我不能直接与数据库通信,我应该只与域模型通信。谢谢你的回答。你知道这对性能的影响吗?在常规批处理中,写操作是在成片的行上完成的,在这种情况下,执行方法为每行调用。您必须尝试并找出答案,但大多数ItemWriter都遵循相同的模式。在本例中,我假设实际的dataaccess调用发生在您的存储库中(本例中为FileRepository),这在循环之外。谢谢你的回答。你知道这对性能的影响吗?在常规批处理中,写入操作是在成片的行上完成的,在这种情况下,会为每一行调用execute方法。你必须尝试并找出答案,但大多数ItemWriter都遵循相同的模式。在这种情况下,我假设实际的dataaccess调用发生在循环之外的ARepository(本例中为FileRepository)中。