Доктрина 2: странное поведение при вставке пакетной обработки объектов, которые ссылаются на другие объекты

Я пытаюсь использовать метод пакетной обработки, описанный здесь: 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 ()