1

Is it possible to get an entity without loading its associated entities using findOneById()? In some cases such as just checking the entity exists or not, I don't need to load all of its associated entities, for example,

$entity = $em->getRepository('EstateBundle:MyEntity')->findOneById($id);
if (!$entity) {
    throw $this->createNotFoundException('Unable to find the entity.');
}

Otherwise, I think it could lead to performance issue. In CakePHP, it is possible using an option recursive. I'm looking for such kind of option in Symfony and Doctrine. I think this is a common question, but I can't find any documentation about this.

Sithu
  • 4,752
  • 9
  • 64
  • 110
  • I hope this helps you get started: http://stackoverflow.com/questions/26891658/what-is-the-difference-between-fetch-eager-and-fetch-lazy-in-doctrine – tomazahlin Jul 08 '15 at 07:08
  • Maybe you still need another solution or want to try it: Use partial loading `$qb = $this->createQueryBuilder('a'); $query = $qb->select(array('partial a.{id,name}')) ->where("a.id = :myid") ->setParameter("myid", $id) ->addOrderBy('a.name', 'ASC') ->getQuery(); return $query->getSingleResult();` – CiTNOH Aug 05 '15 at 07:42

2 Answers2

1

EDIT: removed the getReference possibility, as it is no solution for the question.

Second possibility is to change your entity by fetch="EXTRA_LAZY" Doctrine extra lazy

In general: Your assoiciated Entity is selected LAZY by default, means it only gets loaded, when first accessing it. Maybe your problem is not relevant in first place? To be sure use the development mode of Symfony. There you have the option to see, which database queries were actually executed.

EDIT: You can then use getRepository("bundle:entity")->find($id) to check existence. For actually querying it write a method like:

$q = $this->createQueryBuilder('o,u,i')
        ->select('o')
        ->from("bundle:entity","o")
        ->leftJoin("o.prop","u")
        ->leftJoin("o.prop2","i")
        ->where('o.id = :id')
        ->setParameter('id', $id)
        ->getQuery();

This then fetches the other entities as well.

Hope that helps

CiTNOH
  • 186
  • 1
  • 8
  • `getReference()` cannot be used to check if the entity exists or not. It always returns an empty entity with its id loaded and `__IS_PROXY__ == true`. I think `EXTRA_LAZY` could not be my option because I don't want to add it in the yml mapping configuration. I'm just looking for dynamically enable/disable option. – Sithu Jul 17 '15 at 02:00
  • You are right. I think you have to change your yml config then. You should write different methods in you Repository one for only catching the object or use `find()` and another, where you actually JOIN the needed entities. – CiTNOH Jul 17 '15 at 07:40
  • Unfortunately, it is same result as `findOneBy`. `createQueryBuilder` fetches the entities of `oneToMany`, but `ManyToOne` is loaded with an empty proxy object. I guess `findOneBy` internally calls `createQueryBuilder()`. – Sithu Jul 17 '15 at 10:51
  • 1
    Ok I looked deeper into my entities again. `@ORM\OneToMany(targetEntity="TargetEntity", mappedBy="targetproperty",cascade={"persist", "remove"})` is my example for the relation. When I query my BaseEntity with `find($id)` or `findall()` TargetEntity is not loaded. When I access it, it gets queried. This is normal behaviour as you want it. When I build a querybuilder ***with*** the left join (as above) then it gets loaded in one step. So the basic behaviour of this relation should work as well. Could you post your relation of the entity? – CiTNOH Jul 17 '15 at 14:18
  • I think you are right @CiTNOH. The assoiciated entities are selected LAZY by default. I'm trying to debug using `\Doctrine\Common\Uitl\Debug::dump($entity)` which could cause all associations loaded. From my day-to-day work, I found that I had to use `createQueryBuilder` with `join`+`select` for EAGER loading (I don't want to use ORM setting) – Sithu Oct 14 '15 at 08:17
0

By default if you perform a findOneBy(), Doctrine will fetch only one entity with all its data, but not the relations. If you really want to check if the entity exists or not, add a select('id') statement, this way your object will be really small (the id will be hydrated nothing more).

Then if your object has relations, if you do $your_object->relations(). Doctrine will lazy load the relation leading to an extra query.

To prevent this from happening, you can forbid Doctrine's lazyloading by creating your own method :

 public function findMyObjectById($id)
    {
        $q = $this->createQueryBuilder('o')
            ->select('o.id')
            ->where('o.id = :id')
            ->setParameter('id', $id)
            ->getQuery()
            ->setHint(Query::HINT_FORCE_PARTIAL_LOAD, true);

        return ($q->getResult());
    }
  • I always see `findOneById()` returning the entity with all of its association fully loaded. – Sithu Jul 17 '15 at 02:20