延迟加载Doctrine一对一关联

时间:2016-04-06 11:30:36

标签: symfony doctrine-orm

我最近一直在阅读很多关于学说的内容,并且我已经看到了避免双向一对一关联的一般建议。 This page(自2015年6月起)声明:

... you should avoid bidirectional one-to-one associations in Doctrine. 
    The inverse side of a one-to-one association cannot be lazy loaded.

我假设无法延迟加载意味着像一样必须加载

该页面也被称为" Doctrine Performance Traps",所以它看起来很吓人:)

由于manual on one-to-one没有提到这一点,我决定自己测试一下。我在测试应用程序中发现了几个已经使用一对一关联的类,所以这很容易:

class Recipe
{
    /**
     * @ORM\OneToOne(targetEntity="Image")
     * @ORM\JoinColumn(name="image_id", unique=true, referencedColumnName="id")
     */
    private $image;
}

class Image
{
    /**
     * @ORM\OneToOne(targetEntity="Recipe")
     * @ORM\JoinColumn(name="recipe_id", referencedColumnName="id")
     */
    private $recipe;
}

接下来,我尝试在控制器中选择一个图像:

$image = $em->getRepository('AppBundle:Image')->find(658);

在Symfony探查器中,我看到一个没有连接的SQL查询。在转储的图像数据中,在Recipe下,我看到:

+__isInitialized__: false

这意味着Recipe实体是懒惰的?

加载配方时会发生同样的情况:图像变得懒惰。

inversedBy添加到任何实体似乎无法发挥作用。

似乎我正在阅读的文章不正确,或者从那时起教条中的某些内容发生了变化,或者我不理解延迟加载。

问题:

  • 最新版本的doctrine lazy-load双向一对一吗?
  • 为什么双向一对一关联经常被认为对性能有害?

据我所知,很多时候我可以在不使用双向映射的情况下逃脱,但有时我真的需要拥有它们,我只是想了解这个决定的价格。

谢谢!

2 个答案:

答案 0 :(得分:1)

我认为你在懒惰和渴望加载之间会产生一些混淆。

延迟加载不会使用join语句加载相关数据:当您尝试访问子对象(来自父对象)时,您实际上会调用将触发的代理对象具有适当条件的select语句。当您想要获取将被访问的数据时,应该避免延迟加载。

Eager Loading 在单个查询中使用join语句加载相关数据。这将有助于您解决" n + 1"开销。

假设你有一些分类在一个表中的类别和子类别(我知道,这对于数据库规范化方法很奇怪,但会帮助我们得到分数):你将显示一个带有类别的菜单和子类别。通过Eager Loading,您可以为每个类别创建一个select语句来获取子类别数据(即您将在菜单上显示的名称)。

关于双向一对一关系的问题,双向加载它导致开销的原因很简单:让我们假设A与B有一对一的关系。当你加载A时你将创建一个直接指向B的代理对象。如果你设置双向关系,你的代理对象B也将包含一个(不可用的)A代理对象。

希望这有帮助(而且我实际上并没有犯任何错误)(:

答案 1 :(得分:1)

您对双向一对一关联的映射不正确。通常,您只在关联的一端有@JoinColumn,而不是在两端:

<?php
class Recipe
{
    /**
     * @ORM\OneToOne(targetEntity="Image", mappedBy="recipe")
     */
    private $image;
}

class Image
{
    /**
     * @ORM\OneToOne(targetEntity="Recipe", inversedBy="image")
     * @ORM\JoinColumn(name="recipe_id", referencedColumnName="id")
     */
    private $recipe;
}

请参阅http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/association-mapping.html#one-to-one-bidirectional

如果您设置这样的映射并加载Recipe,您会看到带有JOIN表的预期Image

相关问题