根据我在网上读到的内容,从数据库加载的聚合必须处于完整状态。这意味着它必须能够访问其中的所有实体,这些实体也是从数据库加载的,这样聚合就永远不会处于无效/不完整状态。
如果集合中包含一个实体,例如可以有数百万个实体。 Aggregate A
包含 Entity B
以及 Entity C
. 现在最坏的情况可能是100 Entity B
下的示例 Aggregate A
但可能有数百万(如果不是数十亿)的 Entity C
低于 Aggregate A
.
用例:
用例是我想删除 Entity C
从 Aggregate A
使用id。在 DDD
我得先装上 Aggregate A
并将其所有实体加载到内存中。然后使用以下方法移除该项:
public class AggregateA extends AbstractAggregateRoot<AggregateA>{
private String aggregateId;
private Map<String, EntityC> entityC;
public void removeEntityC(String idToRemove) {
this.entityC.remove(idToRemove);
registerEvent(new EntityCRemoved(aggregateId, idToRemove));
}
}
问题是:
将数百万个实体加载到内存中以执行任何 Write Operation (Command in CQRS)
因为一个请求似乎不是正确的方式。
我是不是漏了什么?
2条答案
按热度按时间r8xiu3jd1#
我认为这将是重新考虑你的总体边界的第一个迹象。一种可能的解决方案是将实体c视为聚合,并通过id引用聚合a。这取决于你的业务领域,所以这只是一个模糊的建议。您可以在aggregate a中或在生成aggregate c示例的独立域服务中使用factory方法。一般来说,您应该避免在一个聚合中加载数百个实体,因为它将跨越该聚合周围的巨大事务边界。
zaq34kh62#
您误解了ddd的“加载完整集合”命令。就像你说的,这样做是完全不切实际的。我的建议是加载所需的聚合的完整部分。
例如:我的操作(尽管是人为的)是在一个有数百万条评论的博客条目中编辑一条特定的博客评论。我要做的是从存储库中加载博客聚合和我要更新的单个评论。然后我会继续让博客更新评论。当然,另一种设计选择是只加载注解(因为您可以用它的id标识它),但这将是加载一个不完整的实体,因为它缺少聚合根(这是授权要求不要做的)。
当然,这里的一个问题是在ddd中进行批量更新变得非常有效。这是设计上的弱点,也是ddd之外解决的问题。