Doctrine部分查询返回完整对象

时间:2013-08-28 20:32:17

标签: symfony doctrine-orm symfony-2.3

我正在尝试优化查询,因为我需要一个简单的列表作为一个附属于多个实体的实体。 所以我创建了这个查询,你应该只给我一个id和名字:

public function findAllOrderByName() {
    $qb = $this->createQueryBuilder('a');
         $query = $qb->select(array('partial a.{id,name}'))
                 ->addOrderBy('a.name', 'ASC')
                 ->getQuery();

         return $query->getResult();
}

在控制器中返回它:

public function getInstrumentsAction()
{
    $instruments = $this->getDoctrine()->getRepository('AcmeInstrumentBundle:Instrument')->findAllOrderByName();

    return array('instruments' => $instruments);
}

而不是仅仅让我回到两个阵营,给我完整的对象,从而包括其他相关实体的所有领域。

为什么不起作用?

1 个答案:

答案 0 :(得分:5)

它实际上完全按照设计工作。您所观察到的是您的相关实体的延迟加载。

首先添加:

echo $query->getSQL() . "\n";
return $query->getResult();

你会看到类似的东西:

SELECT p0_.id AS id0, p0_.name AS name1 FROM instrument p0_ ORDER BY p0_.name ASC

因此,只有您要求实际查询的两个字段。

echo sprintf("Instrument %s %s %s\n",
     $instrument->getName(),$instrument->getSomeotherScalervalue());

你会看到,当名字被回显时,其他一些值甚至不在仪器表中。

就关系而言,让我们假设乐器与人之间有一种关系。

$persons = $instrument->getPersons();

你会期望$ people是一个空数组,但它实际上是一个相当聪明的Doctrine \ ORM \ PersistentCollection。一旦你尝试用$ person做任何其他事情(即使是像count($ persons)那样简单的事情,也会触发另一个查询,并且所有链接的人物对象都会被加载。

这就是你所看到的。您实际上可以在logs / dev.log中查看查询。只要您拉入仪器,就只会生成一个查询。一旦你尝试用关系做某事,另一个查询就会消失。

解决方法

  1. 不要试图访问关系。

  2. 在访问关系之前,您可以执行$ persons-> setInitialized(true);这将阻止加载。显然有点痛苦。

  3. 由于优化是您的目标,因此只返回一个数组结果。根本没有任何对象。

  4. 您也可以继续在查询中加入您的关系,但使用partial来引入相关实体的ID。您的查询工作有点困难,但您不必担心会触发其他查询。

  5. 如果有一些方法可以在特定查询的基础上阻止延迟加载,那将会很好。但是,如果有,我一直无法找到它。