首页 > 解决方案 > 当它们是数据库规范化的一部分时如何处理域中的关系

问题描述

你有Job*--1 ,所以在你的数据库中你的表中Board会有一个。board_idjobs

现在,在域中,Job可以没有Board. 因此,考虑向它添加boardId属性对我来说并不合乎逻辑。

可以通过 管理它BoardRepository吗?例如打电话给BoardRepository.addJob(Board board, Job job)?所以存储库会将作业映射到数据库对象,然后board_id在插入时添加字段?

问题是......如果我想通过查询作业/jobs/{id},我需要boardId在域类中有属性,所以它不会映射到正确的 DTO。

希望我很清楚。

标签: domain-driven-designclean-architecturehexagonal-architecture

解决方案


通常每个存储库都有一个聚合。所以 Repository.addJob(Board board, Job job) 似乎不是一个好的选择。我不知道您的问题域..但是当我们将董事会作为一个集合或集合的根实体时,董事会负责管理其工作。所以它保留了一份工作列表,其中 Job 可能是另一个实体。一般来说,聚合是一个连接域对象的集群,它的作用就像一个门面,用于操纵它的状态以及它的实体和值对象的状态。通过应用这些原则,您可能会以这样的方式结束:

Board.addJob(Job job)    
BoardRepository.add(Board board)

如果您的查询变得过于复杂并且不适合您的 DDD 模型,那么只需添加一个将简单 dto 映射到数据库的附加 QueryService 就可以在逻辑上分离写入和读取模型。希望我能提供一点帮助:)

存储库是您对持久性策略的抽象。因此,您将在域层中为您的存储库提供一个接口:

interface BoardRepository {
    add(Board board);
    update(Board board);
    delete(BoardId id);
    get(BoardId id);
}

如果您将使用 SQL 持久性策略,那么您将在例如您的基础设施层中实现此接口,如下所示。

class SqlBoardRepository implements BoardRepository {
    ...
}

所以是的,存储库负责持久化聚合。每个聚合将有一个存储库!不是每个实体都有一个存储库!

主键和外键是与数据库相关的主题,通常您在域模型中并不关心它们。域模型中的实体由业务键(也可以用作主键)标识。例如,isbn 标识世界范围内的一本书,它是 Book 实体的业务键,也可以用作数据库中的主键。有时,当在持久性模型中使用业务键过于复杂时,您可以在实体中使用额外的代理键,它主要在持久层上标识您的实体。您使用数据库中的业务或代理键对域对象之间的关系进行建模,并且 sql 存储库负责将域模型映射到数据库,反之亦然。

也许你应该阅读一些关于它,然后你会更好地理解。Eric Evans 的蓝皮书或 Vaughn Vernon 的实施领域驱动设计是一个好的开始 :)


推荐阅读