Doctrine partial queries return the complete object

拈花ヽ惹草 提交于 2020-01-04 04:04:46

问题


I'm trying to optimize the query as I need a simple list as an entity that is affiliated with several entities. So I created this query, you should just give me back the id and name:

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

         return $query->getResult();
}

return it in the controller like this:

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

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

rather than just give me back the two camps, gives me the complete object, thus including all the fields of other related entities.

Why did not it work?


回答1:


It actually worked exactly as designed. What you are observing is the lazy loading of of your related entities.

Start by adding:

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

You see something like:

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

So only the two fields you asked for actually being queried.

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

You will see that while name is echoed, some other value is not even though it's in the instrument table.

As far as relations go, let's suppose instrument has a oneToMany relation to persons.

$persons = $instrument->getPersons();

You would sort of expect $persons to be an empty array but it's actually a rather smart Doctrine\ORM\PersistentCollection. As soon as you try to do anything else with $person (even something as simple as count($persons) another query is triggered and all the linked person objects will get loaded.

So that is what you are seeing. You can actually see the queries in your logs/dev.log. As long as you just pull in the instrument then only one query is generated. As soon as you try to do something with a relation, another query goes out.

Work Arounds

  1. Don't try to access relations.

  2. Before accessing a relation you could do $persons->setInitialized(true); That will prevent loading. obviously a bit of a pain.

  3. Since optimization is you goal then just return an array result. No objects at all.

  4. You can also go ahead and join your relations in the query but use partial to just bring in say the id of the related entity. Your query works a bit harder but you won't need to worry about additional queries getting triggered.

It would be kind of nice if there was some way to prevent lazy loading on a query specific basis. But if there is, I have not been able to find it.



来源:https://stackoverflow.com/questions/18497641/doctrine-partial-queries-return-the-complete-object

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!