Я пытаюсь использовать метод пакетной обработки, описанный здесь: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/batch-processing.html
мой код выглядит так
$limit = 10000; $batchSize = 20; $role = $this->em->getRepository('userRole')->find(1); for($i = 0; $i <= $limit; $i++) { $user = new \Entity\User; $user->setName('name'.$i); $user->setEmail('email'.$i.'@email.blah'); $user->setPassword('pwd'.$i); $user->setRole($role); $this->em->persist($user); if (($i % $batchSize) == 0) { $this->em->flush(); $this->em->clear(); } }
проблема в том, что после первого вызова em-> flush () также выделяется $ role, и для каждых 20 пользователей создается новая роль с новым идентификатором, что не то, что я хочу
есть ли доступ к этой ситуации? только один, который я мог бы сделать, – это получить объект роли пользователя каждый раз в цикле
благодаря
clear()
отделяет все сущности, управляемые менеджером сущности, поэтому $role
также отключается, и попытка сохранить отдельный объект создает новый объект.
Вы должны снова получить эту роль после очистки:
$this->em->clear(); $role = $this->em->getRepository('userRole')->find(1);
Или просто создайте ссылку:
$this->em->clear(); $role = $this->em->getReference('userRole', 1);
В качестве альтернативы ответу arnaud576875 вы можете отделить $ user от менеджера объектов, чтобы он мог быть GC'd немедленно. Вот так:
$this->em->flush(); $this->em->detach($user);
Редактировать:
Как отметил Джефф, это будет только отделять последний созданный пользовательский объект. Поэтому этот метод не рекомендуется.
Другой альтернативой является merge
роли после ясного:
if (($i % $batchSize) == 0) { $this->em->flush(); $this->em->clear(); $this->em->merge($role); }
Я не уверен, как дорогое слияние () есть – если бы я должен был догадаться, я бы пошел с предложением Арно использовать getReference ()