Метод очистки Doctrine EntityManager во вложенных объектах

Я хотел бы использовать пакетная обработка доктрины чтобы оптимизировать вставку большого количества сущностей. Проблема в методе Clear. Это говорит о том, что этот метод отсоединяет все сущности, которыми управляет EntityManager. Итак, что я должен делать в ситуации, когда у меня есть родительский объект, у которого много детей, и у каждого ребенка есть свои дети, например:

  • riseSession
    • трек
      • точки

Таким образом, у меня есть 1 поездка на сессию, 3 дорожки, и каждая дорожка имеет на время 2000 очков. Я мог бы использовать пакетную обработку в последнем цикле, который отвечает за сохранение точек. Но если я использую понятный метод, то как установить родителей для точек и треков? Чистый метод отсоединит их, верно?

4

Решение

Скоро у тебя будет предел памяти. Идея flush() в партиях это нормально, но нужно clear() EntityManager в конце каждой партии освободить использованную память.

Но в вашем случае у вас будет ORMInvalidArgumentException (a.k.a. «новая сущность, основанная на отношениях»), если Вы позвоните $child->setParent($parent); после того как ты сделал $entityManager->clear();,

Проблема в том, что $parent сейчас в detached состояние в UnitOfWork, Таким образом, вы должны положить его снова в managed государство. Это можно сделать с помощью $entityManager->merge(); или просто с помощью $parentRepository->find($parent->getId());,

Просто убедитесь, что все сущности managed состояние после каждого clear() в случае, если вы собираетесь использовать их позже.

4

Другие решения

Если все ваши 40000 объектов уже загружены в память, вы можете просто использовать код без очистки. Очистка в диспетчере сущностей используется для оптимизации памяти в скрипте PHP. Если у вас достаточно памяти для хранения всех объектов, вам вообще не нужно очищать менеджер сущностей.

Для оптимизации памяти в этом случае вы можете unset($entity) после каждого упорства

А чтобы соответствовать пропускной способности соединения с БД, вы можете сгруппировать несколько объектов, как в примере.

$batchSize = 20;
for ($i = 1; $i <= 10000; ++$i) {
$em->persist($entities[$i]);
unset($entities[$i]);
if (($i % $batchSize) === 0) {
$em->flush();
}
}
$em->flush(); //Persist objects that did not make up an entire batch
1

По вопросам рекламы [email protected]