Domain driven design DDD和批处理(例如使用Spring批处理)

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并不

我想将SpringBatch用于批处理应用程序。我已经有了一个按照DDD设计的域模型。我的问题是批处理(在我的例子中,使用SpringBatch)如何适合DDD

例如,我有一个聚合根A,它的一个子实体是实体B。A有一个包含一个或多个B的列表。当每一行对应于Bs列表上的操作(添加、删除…)时,批处理应用程序接收一个文件。在我的聚合根A中,每个操作都有一个方法(例如addB、delB…)。使用SpringBatch,我应该使用哪个ItemWriter?我认为JdbcBatchItemWriter并不合适,因为我应该只通过域处理数据。是否有关于批处理使用DDD的最佳实践


谢谢

我不想假装知道这方面的最佳实践是什么,但考虑到您的设计目标,我会这样做。假设我们有一个文件对象,即您的聚合,而不是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)中。