3

在阅读了很多帖子之后,我意识到如果一个概念/上下文存在聚合根,我们需要为整个概念/上下文建立一个存储库。

如果是这样的话,我认为内部实体不会有任何存储库。如果是这样,这些内部实体如何保存到数据库中?

我在聚合根目录下有许多内部实体。所以,想知道如果我需要在聚合根存储库下保存所有内部实体,它会变得臃肿。请建议在这种情况下可以做什么。

此外,我的内部实体将在持久性级别访问它们自己的每个表。如果我不允许以这种方式存储内部实体,请纠正我。

示例
考虑我有一家餐厅作为聚合根。它可以对名为 Review 的实体进行分组。评论存在于餐厅,没有评论就无法存在。

在这里,如果 Review 是一个内部实体,并且餐厅可能有许多评论,则评论将保存在单独的表中。但由于餐厅聚合根只有一个餐厅存储库,因此如何/在哪里处理保存评论。

4

3 回答 3

6

我同意其他答案中提出的一些观点,即您可能不想那样建模,但我认为您的问题本身尚未得到回答。例如,它非常好。

所以这里是:

您不会为实体创建存储库(如在 DDD 存储库中),仅为聚合根创建存储库。因此,在您的示例中,应用层可能类似于:

Restaurant restaurant = restaurantRepository.findById(23)
restaurant.addReview(review)
restaurantRepository.save(restaurant)

另请注意,操作是在聚合根上完成的。所以一般来说,应用层中的命令通常是:加载聚合,对其执行操作,保存它

聚合被保存为一个整体和实体。存储库背后发生的事情取决于您的基础架构。当然,由于存储库属于域,我们不关心那里的基础设施。

那么基础设施层中的实现(这些只是它的一些示例):

  1. 在文档数据库中,您将拥有一个存储库的实现,它将文档作为一个整体保存到数据库中。(文档存储和 DDD 在这里非常匹配,因为聚合 = 文档)
  2. 如果您要在一个简单的文本文件中将聚合序列化到磁盘,您可能有一个存储库实现,每个实体都有一个序列化器,值对象来执行序列化。
  3. 如果您有 RDBMS,您确实希望将实体存储在它们自己的表中。在这里你可以使用:

    • 一个 ORM 框架,只保存根实体,让框架自动保存/删除/更新子实体
    • 使用 DAO 模式并为每个表/实体创建一个 DAO
    • ...

也看看这个问题

此外,在某些情况下,您可能会仅出于技术原因拆分聚合。如果您要拥有一个包含大量实体的聚合,并且处理它变得很重,那么您可能希望纯粹出于技术原因将其拆分为两个聚合。但这是你试图避免的事情,只有在真正必要时才会这样做。

于 2020-03-27T16:42:51.147 回答
2

我想补充CPerson的答案。

这种不深入上下文的讨论通常是没有意义的。每个案例都是特定于上下文的,很少归结为持久性问题。

在上述情况下,我永远不会将 Review 建模为 Restaurant 聚合中的实体。这不是持久性问题,而是建模问题。

那里有一些 DDD 书籍,我相信阅读一些博客文章不足以理解 DDD 的战略和战术模式。其中一种模式确实是聚合模式。简而言之,聚合是一致性边界。聚合始终是特定于上下文的(就像其他任何东西一样)。

如果您正在对餐厅管理系统或食品配送系统进行建模,那么评论可能会在单独的上下文中。没有像“餐厅环境”这样的环境。这就是有界上下文模式的重点。在您的示例中,它可能是餐厅评论上下文。评论发生的事情与食物、营业时间和餐桌预订无关。

如果您正在为 TripAdviser 之类的东西建模,那么您基本上只有评论。在这种情况下,评论或多或少与正在评论的内容无关。然后,您的模型完全不同。

评论的数量在不断增长,因此将所有评论作为实体进行聚合并没有多大意义。同样,聚合是一致性边界。如果另一条评论是一星,您会说无法发布评论吗?我不这么认为。关于评论,您试图在 Restaurant 聚合中保护的不变量是什么?您是否需要限制评论数量以根据这些评论更改餐厅的状态?我不认为是这样。因此,评论本身可以是一个汇总,因为所有评论都是完全独立的。

评论聚合中的餐厅可以是一个简单的值对象,其中包含餐厅 ID。在构建此值对象时,您将确保给定的餐厅确实存在并开放供评论。当餐厅消失时,您确实需要清除评论。但它也是特定于上下文的。餐厅可能会关门,但无论如何你都会保留评论。

于 2020-02-28T08:31:48.103 回答
1

如果是这样的话,我认为内部实体不会有任何存储库。如果是这样,这些内部实体如何保存到数据库中?

聚合代表一致性边界。如果一个实体由一个聚合拥有并且需要确保一致性,那么它应该与聚合根一起持久化。

所以,想知道如果我需要在聚合根存储库下保存所有内部实体,它会变得臃肿。

是的,会的。如果这是一个真正的问题,您可以考虑使用 ORM。ORM 将在内存中维护以聚合根为根的图,并确保在必要时保留更改。

此外,我的内部实体将在持久性级别访问它们自己的每个表。如果我不允许以这种方式存储内部实体,请纠正我。

尝试将您的域与您的持久性策略分开考虑。您有一个映射到关系模式的域模型。关系模式不应驱动域的设计。

于 2020-02-27T19:17:00.400 回答