为什么不能延迟加载Doctrine中的OneToOne关系的原因是什么?

时间:2018-11-12 02:42:54

标签: doctrine-orm lazy-loading one-to-one

我有一个PersonAdmin实体。一个Person只能有一个Admin,但是我并不需要一直保持管理员状态。当我列出所有与admin相关的人员时,该学说将从DB中加载所有管理员。为什么会这样?

1 个答案:

答案 0 :(得分:0)

在一对一关联的情况下(和类似的情况,例如,在延迟加载一对多关联的情况下),Doctrine为关联实体生成所谓的proxy objects。这些代理对象模仿目标实体的界面,但仅在访问 non-id 字段时才触发从数据库加载实际数据。

由于这种情况,当您获取Person个实体的列表时-您不会获得从数据库中获取的Admin个实体的列表,但会收到Admin个代理的列表代替。除非您(偶尔或有意)尝试访问Admin实体的某些属性(可以安全访问的id实体除外),Doctrine不会尝试获取任何Admin信息来自数据库。

请考虑以下简化的设置,以AB实体进行一对一关联:

// A.php

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity()
 */
class A
{
    /**
     * @var integer
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;
    /**
     * @var B
     * @ORM\OneToOne(targetEntity="App\Entity\B")
     */
    private $b;

    /**
     * @return int
     */
    public function getId(): int
    {
        return $this->id;
    }

    /**
     * @return B
     */
    public function getB(): B
    {
        return $this->b;
    }
}

// B.php

<?php

namespace App\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity()
 */
class B
{
    /**
     * @var integer
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;
    /**
     * @var string|null
     * @ORM\Column(type="string", nullable=true)
     */
    private $name;
}

通过查看调试器或使用反射,可以证明A::$b包含代理对象:

$entities = $this->getEntityManager()->getRepository(\App\Entity\A::class)->findAll();
/** @var \App\Entity\A $a */
$a = array_shift($entities);
$class = (new \ReflectionObject($a->getB()))->getName();

在这种情况下,$class变量的值将是Proxies\__CG__\App\Entity\BApp\Entity\B的Doctrine代理对象),而不是正常实体对象的App\Entity\B