DDD - 使用Doctrine 2的有界上下文之间的关联映射

时间:2015-12-03 15:00:00

标签: orm doctrine-orm domain-driven-design bounded-contexts

我正在努力理解使用Doctrine 2实现来自不同有界上下文的两个实体之间的关联映射的正确方法。假设有两个" User"和"发布"属于"用户"的实体和"内容"有限的上下文。还有一个用户"概念在"内容"决定一个" Post"通过多对一协会。因此,"用户"在"内容" context只是一个包含用户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规则,但会影响数据库架构(通过外键约束删除"用户"" posts"表之间的数据库级关系)。

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

1 个答案:

答案 0 :(得分:4)

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

正如您所正确观察的那样,应避免不同BC之间的关联。在另一个BC中引用实体的正确方法是ID。

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

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