3

I have Partner entity with two relation:

/**
 * @var PartnerSettings
 * @ORM\OneToOne(targetEntity="PartnerSettings", mappedBy="partner", cascade={"persist", "remove"}, fetch="LAZY")
 */
private $settings;

/**
 * @var PartnerRating
 * @ORM\OneToOne(targetEntity="PartnerRating", mappedBy="partner", cascade={"persist", "remove"}, fetch="LAZY")
 */
private $rating;

...getRepository(Partner::class)->findAll() work correctly, one query was made,but when I create queryBuilder:

return $this->createQueryBuilder('p')
    ->getQuery()
    ->getResult();

doctrine make 31 queries(i have 10 partners)... in debug toolbar i saw select queries to settings and rating for every partner. I don't want it in this case. Additionally, in every querybuilder where I used join to partners, setting and rating are selected too.

answer

->setHint(Query::HINT_FORCE_PARTIAL_LOAD, true);

did the job

Caconde
  • 4,177
  • 7
  • 35
  • 32
Uni
  • 71
  • 1
  • 6

3 Answers3

1

This behaviour is known as the N + 1 selects problem. To reduce database queries, you might want to consider the following approach.

First, retrieve all partners:

$partners = $em->createQueryBuilder()
    ->select("p")
    ->from("Parent", "p")
    ->where(/*...*/)
    ->setParameter(/*...*/)
    ->indexBy("p.id")
    ->getQuery()->getResult();

Now load all children at once, in two queries:

$settings = $em->createQueryBuilder()
    ->select("s")
    ->from("PartnerSetting", "s")
    ->where("IDENTITY(s.partner) IN (?1)")
    ->setParameter(1, array_keys($partners))
    ->getQuery()->getResult();

$ratings = $em->createQueryBuilder()
    ->select("r")
    ->from("PartnerRating", "r")
    ->where("IDENTITY(r.partner) IN (?1)")
    ->setParameter(1, array_keys($partners))
    ->getQuery()->getResult();

Doctrine will now have all of the retrieved entities are stored in memory. So when, for example, you do a $parnter->getRatings(), you don’t trigger a new DB query, instead the entity is filled from memory.

lxg
  • 12,375
  • 12
  • 51
  • 73
1

just define the table AND the relation in the select

$qb->select('g', 'gi');

and now it works

0

Just mapped relation: @ORM\OneToOne(targetEntity="ENTITY", mappedBy="MAPPEDBY", fetch="EAGER")

l13
  • 529
  • 3
  • 11