1

我对处理学说的延迟加载机制的正确方法有疑问。我有一个通过@ManyToOne 引用另一个实体的实体:

class Entity {
    ...
    /**
     * @ManyToOne(targetEntity="AnotherEntity")
     * @JoinColumn(name="anotherEntityId", referencedColumnName="id")
     */
    protected $anotherEntity;
    ...
}

class AnotherEntity {
    /**
     * @var integer $id
     * @Column(name="id", type="integer", nullable=false)
     * @Id
     * @GeneratedValue(strategy="IDENTITY")
     */
    private $id;

    /**
     * @var string $someValue
     * @Column(name="someValue", type="string")
     */
    private $someValue;
    ...
}

Doctrine 现在为 AnotherEntity 生成一个代理,该代理在其 getter 上实现延迟加载:

public function getSomeValue()
{
    $this->__load();
    return parent::getSomeValue();
}

如果我现在有一些 Entity 实例没有 AnotherEntity 的引用对应项($anotherEntityId 为 0 或 null)。然后学说似乎生成了另一个实体的一个空对象,并使所有实体对象的 $anotherEntity 变量都指向它。空对象未初始化,因为我们想要延迟加载。当我这样做时,我现在得到一个 EntityNotFoundException :

$entiy->getAnotherEntity()->getSomeValue();

那太棒了!我访问的另一个实体在数据库中不存在,所以我得到了这个异常。但是当我对第二个实体(以及之后的所有其他实体)执行相同操作时,我没有得到这个异常,因为它们都指向另一个实体的同一个实例,并且学说在第一次调用中将其标记为已初始化。所以现在我正在访问一个逻辑上不存在但没有出现任何异常的对象 - 我只是从 getSomeValue() 中获取未初始化的变量,例如一个空字符串。

您知道如何让我的应用程序识别出该对象不存在,而不仅仅是接受空值吗?

4

2 回答 2

2

我想这是一个教义错误,因为代理被标记为已初始化,即使它不是在抛出 EntityNotFoundException 时也是如此。这是为每个代理生成的代码原则:

public function __load()
{
    if (!$this->__isInitialized__ && $this->_entityPersister) {
        $this->__isInitialized__ = true;

        if (method_exists($this, "__wakeup")) {
            // call this after __isInitialized__to avoid infinite recursion
            // but before loading to emulate what ClassMetadata::newInstance()
            // provides.
            $this->__wakeup();
        }

        if ($this->_entityPersister->load($this->_identifier, $this) === null) {
            throw new \Doctrine\ORM\EntityNotFoundException();
        }
        unset($this->_entityPersister, $this->_identifier);
    }
}

在 ProxyFactory 文件中,您可以找到此代码,并在抛出异常之前添加以下行,问题就解决了:

$this->__isInitialized__ = false;

有了这个,您每次需要时都会得到异常。

顺便说一句:学说人们自己已经讨论过这个问题,但修复似乎不在当前版本中:https ://github.com/doctrine/doctrine2/pull/364

于 2012-11-12T10:09:22.143 回答
0

这是关于教义 2 的错误,请参见此处https://github.com/doctrine/doctrine2/issues/3945

用户和地址之间的关系是一对零或一。当双方都有记录时,一切都很好。当右侧(地址)没有相关记录时,调用$user->getAddress();总是返回一个实例。在该实例上调用方法会导致异常:

致命错误:未捕获异常 'Doctrine\ORM\EntityNotFoundException' 并带有消息'找不到'地址'类型的实体。在第 176 行的学说/orm/lib/Doctrine/ORM/Proxy/ProxyFactory.php

预期行为: $user->getAddress()当右侧为空时应返回 NULL。

注意:请注意该地址是通过外国实体(用户)识别的

于 2017-11-24T19:43:25.070 回答