原则:防止在需要单个元素时延迟加载整个集合


Doctrine: Prevent lazy loading whole collection when need a single element

我有一个实体Parent,与Child oneToMany关系,与User有关。

Parent Child集合使用 user_id 进行索引,这意味着它利用indexBy映射选项。

Entity'Parent:
  type: entity
  oneToMany:
    children:
      targetEntity: Entity'Child
      mappedBy: parent
      indexBy: user_id 
      cascade: [ persist ]

现在,在Parent中,我想要一种方法来告诉我其集合中是否有特定UserChild。为此,我在Parent中有以下代码:

class Parent {
    public function hasChild(User $user) { 
        return isset($this->children[$user->getId()]);
    }
}

这按预期工作。

但是这种方法存在性能问题。当我访问Parent::children时,Doctrine 会加载整个集合,可能是几千或Child个实例。

有什么方法可以在不加载整个集合的情况下检查它,但保留当前界面?我希望通过Parent类而不是Child存储库等来完成它。

你看过额外懒惰的联想吗?

版本 2.1 中的新功能。

在许多情况下,实体之间的关联可能会变得非常大。即使在像博客这样的简单场景中。在可以评论帖子的地方,您始终必须假设一个帖子会吸引数百条评论。在 Doctrine 2.0 中,如果您访问了一个关联,它将始终完全加载到内存中。如果您的关联包含数百或数千个实体,这可能会导致非常严重的性能问题。

在 Doctrine 2.1 中,为关联引入了一个名为 Extra Lazy 的功能。默认情况下,关联标记为 Lazy,这意味着首次访问关联的整个集合对象时将填充该对象。如果将关联标记为额外延迟,则可以在不触发集合完全加载的情况下调用集合上的以下方法:

  • Collection#contains($entity)
  • Collection#containsKey($key) (available with Doctrine 2.5)
  • Collection#count()
  • Collection#get($key) (available with Doctrine 2.4)
  • Collection#slice($offset, $length = null)