java—作为聚合根的一部分加载所有实体

bqujaahr  于 2021-07-06  发布在  Java
关注(0)|答案(2)|浏览(368)

根据我在网上读到的内容,从数据库加载的聚合必须处于完整状态。这意味着它必须能够访问其中的所有实体,这些实体也是从数据库加载的,这样聚合就永远不会处于无效/不完整状态。
如果集合中包含一个实体,例如可以有数百万个实体。 Aggregate A 包含 Entity B 以及 Entity C . 现在最坏的情况可能是100 Entity B 下的示例 Aggregate A 但可能有数百万(如果不是数十亿)的 Entity C 低于 Aggregate A .
用例:
用例是我想删除 Entity CAggregate 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) 因为一个请求似乎不是正确的方式。
我是不是漏了什么?

r8xiu3jd

r8xiu3jd1#

我认为这将是重新考虑你的总体边界的第一个迹象。一种可能的解决方案是将实体c视为聚合,并通过id引用聚合a。这取决于你的业务领域,所以这只是一个模糊的建议。您可以在aggregate a中或在生成aggregate c示例的独立域服务中使用factory方法。一般来说,您应该避免在一个聚合中加载数百个实体,因为它将跨越该聚合周围的巨大事务边界。

public class AggregateA {
    public AggregateC createAggregateC(...){
        //create AggregateC and return it with reference set to AggregateA
        return new AggregateC(this.id, ...)
    }
}
zaq34kh6

zaq34kh62#

您误解了ddd的“加载完整集合”命令。就像你说的,这样做是完全不切实际的。我的建议是加载所需的聚合的完整部分。
例如:我的操作(尽管是人为的)是在一个有数百万条评论的博客条目中编辑一条特定的博客评论。我要做的是从存储库中加载博客聚合和我要更新的单个评论。然后我会继续让博客更新评论。当然,另一种设计选择是只加载注解(因为您可以用它的id标识它),但这将是加载一个不完整的实体,因为它缺少聚合根(这是授权要求不要做的)。
当然,这里的一个问题是在ddd中进行批量更新变得非常有效。这是设计上的弱点,也是ddd之外解决的问题。

相关问题