Doctrine OneToOne всегда загружается в конструктор запросов

У меня есть партнерская сущность с двумя отношениями:

/**
 * @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 () работает правильно, был сделан один запрос, но когда я создаю queryBuilder:

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

doctrine делает 31 запрос (у меня 10 партнеров) ... на панели инструментов отладки я видел выборочные запросы к настройкам и рейтингу для каждого партнера. Я не хочу этого в данном случае. Кроме того, в каждом конструкторе запросов, где я использовал присоединение к партнерам, также выбираются настройки и рейтинг.

отвечать

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

сделал работу


person Uni    schedule 27.02.2018    source источник


Ответы (3)


Такое поведение известно как N + 1 выбирает проблему. Чтобы уменьшить количество запросов к базе данных, вы можете рассмотреть следующий подход.

Сначала извлеките всех партнеров:

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

Теперь загрузите всех потомков сразу, в два запроса:

$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 теперь будет хранить все извлеченные сущности в памяти. Поэтому, когда, например, вы выполняете $parnter->getRatings(), вы не запускаете новый запрос к БД, вместо этого сущность заполняется из памяти.

person lxg    schedule 27.02.2018

Только что сопоставленное отношение: @ORM\OneToOne(targetEntity="ENTITY", mappedBy="MAPPEDBY", fetch="EAGER")

person l13    schedule 27.02.2018
comment
eagerCursor предназначен для ODM, а не для ORM. - person lxg; 27.02.2018
comment
Если вы хотите исправить свой ответ, отредактируйте его напрямую, а не комментируя. - person lxg; 27.02.2018

просто определите таблицу И отношение в выборе

$ qb-> выберите ('g', 'gi');

и теперь это работает

person Lucien Herbiet    schedule 12.06.2020