4

我正在努力理解使用 Doctrine 2 在来自不同有界上下文的两个实体之间实现关联映射的正确方法。假设有两个分别属于“用户”和“内容”有界上下文的“用户”和“发布”实体. “内容”上下文中还有一个“用户”概念,它通过多对一关联确定“帖子”的作者。因此,“内容”上下文中的“用户”只是一个包含用户 ID 的值对象。

我的问题是我应该如何使用 Doctrine 2 来实现这个关联?我有两个解决方案都有自己的问题:

解决方案 1

/**
 * @ORM\Entity
 * @ORM\Table(name="posts")
 * @ORM\HasLifecycleCallbacks()
 */
 class Post
 {
    ...

    /**
     * @ORM\ManyToOne(targetEntity="UserBC\User", inversedBy="posts")
     * @ORM\JoinColumn(name="user_id", referencedColumnName="id")
     */
    private $user;

    ...
 }

解决方案 2

/**
 * @ORM\Entity
 * @ORM\Table(name="posts")
 * @ORM\HasLifecycleCallbacks()
 */
 class Post
 {
    ...

    /**
     * @ORM\Column(type="integer")
     */
    private $user_id;

    ...
 }

在第一个解决方案中,“用户”上下文中的“用户”实体已在“内容”上下文中使用,这违反了关于 BC 彼此独立的 DDD 规则。第二种解决方案尊重 DDD 规则,但会影响数据库模式(通过外键约束删除“用户”和“帖子”表之间的数据库级关系)。

那么,实施此类关联的正确方法是什么?

4

2 回答 2

6

第二种解决方案是正确的。

正如您正确观察到的,应该避免不同 BC 之间的关联。引用另一个 BC 中的实体的正确方法是通过 ID。

这导致 BC 在数据库中没有它们之间的约束。毕竟,你试图让他们独立。如果您觉得这是错误的,那么解决这个问题的唯一方法是重新考虑您的 BC 设计,即合并两个 BC。然而,这是一个不应该由代码气味驱动的决定,而是由您的上下文映射决定的。

注意:仅当它们是聚合根时,才允许通过 ID 引用来自其他 BC 的实体。如果引用的实体不是 AR,那么您就会有另一种设计气味。不是一个严重的问题,但仍然需要考虑。

于 2015-12-04T06:53:20.510 回答
0

对我来说,第二种解决方案也是正确的。我尝试回答@EresDev 问题:

“在方案2中,你怎么知道$user_id是正确的并且已经存在了?”

为此,您应该使用事件。例如,您可以发送一个包含用户 ID 和发布数据的 PostPublicationEvent。此事件由用户 BC 监听。在这里,您可以验证用户是否存在并分派一个新的 UserValidatedEvent 由 Post BC 监听。现在您可以在知道用户有效的情况下发布您的帖子。

于 2022-02-24T18:16:10.773 回答