Доктрина 2: странное поведение при пакетной обработке вставок сущностей, которые ссылаются на другие сущности - PullRequest
6 голосов
/ 15 сентября 2011

Я испытываю метод пакетной обработки, описанный здесь: http://docs.doctrine -project.org / проекты / Доктрина-ОРМ / о / последний / ссылка / партия-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 пользователей новая роль с новым идентификатором создано, а это не то, что я хочу

есть ли обходной путь для этой ситуации? Единственное, что я мог сделать - это извлекать объект роли пользователя каждый раз в цикле

спасибо

Ответы [ 3 ]

15 голосов
/ 15 сентября 2011

clear() отсоединяет все сущности, управляемые менеджером сущностей, поэтому $role также отсоединяется, и попытка сохранить отсоединенную сущность создает новую сущность.

Вы должны получить роль снова после очистки:

$this->em->clear();
$role = $this->em->getRepository('userRole')->find(1);

Или просто создайте ссылку вместо:

$this->em->clear();
$role = $this->em->getReference('userRole', 1);
1 голос
/ 15 сентября 2011

В качестве альтернативы ответу arnaud576875 вы можете отсоединить пользователя $ от менеджера сущностей, чтобы он мог быть немедленно собран GC. Вот так:

$this->em->flush(); 
$this->em->detach($user); 

Edit:
Как указал Джефф, это будет отсоединять только последний созданный пользовательский объект. Так что этот метод не рекомендуется.

0 голосов
/ 15 сентября 2011

Другой альтернативой является merge роль, возвращаемая после очистки:

if (($i % $batchSize) == 0) {
    $this->em->flush();
    $this->em->clear();
    $this->em->merge($role);
}

Я не уверен, насколько дорогой является merge () - если бы мне пришлось угадывать, я бы пошел сПредложение Арно об использовании getReference ()

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...