【问题标题】:Doctrine2 - proxy object among regular objects in getResultDoctrine2 - getResult 中常规对象之间的代理对象
【发布时间】:2017-04-03 03:46:56
【问题描述】:

在我的 Symfony2 控制器中,我有两个查询:
就像在这个例子中:

$object = $this->getDoctrine()->getManager()
           ->createQuery('SELECT PARTIAL o.{id,name,field1} 
                          FROM SomeBundle:SomeEntity o  
                          WHERE o.id = :objectId')
                    ->setParameter('objectId', $objectId)
                    ->getResult();



$objects = $this->getDoctrine()->getManager()
           ->createQuery('SELECT PARTIAL o.{id,name,field1, field2} 
                          FROM SomeBundle:SomeEntity o ')
                    ->getResult();

我在集合$objects 中收到的效果是SomeBundle:SomeEntity 对象的集合,除了我收到到变量$object 的那个我收到代理对象的对象。

如果我输出$objects 集合,并且对于我想要打印包含字段的输出的每个元素:名称、字段1、字段2,我会收到该对象的字段2 的空值。事实上,如果我在与这个一起启动的任何其他控制器中得到这个$object,那么 field2 在每个对该对象的引用上也是空的。

例如,如果我想将每个对象显示为:

name field1 field2

我得到$objects 的以下数组:

nameExample field1Example field2Example
nameExample field1Example field2Example
nameExample field1Example 
nameExample field1Example field2Example
nameExample field1Example field2Example

第三行是$object
如果我在第一个查询中得到 field2,它在第二个查询的 getResult 上也可见。但这使我可以控制在整个请求中为任何实体对象接收的所有字段。

  1. 我做错了什么?
  2. 如何避免这种影响?我仍然想处理不使用多维数组的对象(至于HYDRATE_ARRAY
  3. 有没有办法强制教义总是使用实体对象而不是代理对象?

提前谢谢你。

【问题讨论】:

    标签: symfony doctrine-orm


    【解决方案1】:

    发生这种情况是因为 Doctrine 对其返回的每个实体都有一个内部引用。当您请求之前请求过的实体时,它将重新使用之前的对象。这样做的原因是,如果您尝试操纵同一实体的两个不同副本,则会产生冲突。更多详情请见http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/unitofwork.html#how-doctrine-keeps-track-of-objects

    一个解决方案是在执行第二个查询之前分离您首先获得的实体(使用$em->detach($object)$em->clear())。 请注意,您所做的任何尚未刷新的更改都将消失。

    另一种选择是使用 $em->refresh($object) 刷新实体(这将导致它完全加载)或告诉 Doctrine 它需要为第二个查询刷新所有实体:

    $query = $this->getDoctrine()->getManager()->createQuery('SELECT PARTIAL o.{id,name,field1, field2} FROM SomeBundle:SomeEntity o ');
    $query->setHint(Query::HINT_REFRESH, true);
    $objects = $query->getResult();
    

    这将使 Doctrine 刷新它为第二个查询找到的所有实体。

    【讨论】:

    • 感谢您的回答。我之前考虑过类似的解决方案,但是当您查询与其他实体建立两次一对多关联的实体时,这个问题也出现在一个查询示例中。在这种情况下,您不能分离对象也不能清除 em,因为它在同一个查询中。你怎么看?
    • “关联两次”到底是什么意思?您是否拥有与实体 B 具有两个不同关联的实体 A(例如,具有 created_byupdated_by 字段的 News 实体都指向 User 实体)?而且您以某种方式使用PARTIAL 加载它们?
    • 我的意思是这里描述的情况:github.com/doctrine/doctrine2/issues/5731,所以实际上我还不够精确,因为这种关联变体会注意到这个问题:A->B->A
    • 使用$em->refresh($object) 的显式重新加载应该可以为您解决这个问题,因为它将完全重新加载(所有变量指向)实体。
    猜你喜欢
    • 1970-01-01
    • 2023-03-28
    • 1970-01-01
    • 2016-03-27
    • 2017-10-14
    • 1970-01-01
    • 2011-06-20
    • 1970-01-01
    • 2013-07-23
    相关资源
    最近更新 更多