2011-09-15 10 views
6

Staram się metodę przetwarzania wsadowego opisane tutaj: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/batch-processing.htmlDoctrine 2: dziwne zachowanie podczas wkładki przetwarzania wsadowego podmiotów, które odwołują się inne podmioty

mój kod wygląda następująco

$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(); 
     } 
    } 

problem jest , że po pierwszym wywołaniu em-> flush() również rola $ zostanie odłączona i dla każdych 20 użytkowników tworzona jest nowa rola z nowym identyfikatorem , co nie jest tym, czego chcę

jest dostępne obejście tego problemu? tylko jeden mogę zrobić pracę ma przynieść podmiotowi rolę użytkownika za każdym razem w pętli

dzięki

Odpowiedz

14

clear() odłącza wszystkie podmioty zarządzanych przez kierownika jednostki, więc $role jest odłączana też, i stara się utrzymywać wolnostojący podmiot tworzy nowy byt.

Należy sprowadzić rolę ponownie po jasne:

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

Albo po prostu utworzyć odwołanie zamiast:

$this->em->clear(); 
$role = $this->em->getReference('userRole', 1); 
1

Jako alternatywę do arnaud576875 na odpowiemy mógłby odłączyć $ użytkownika z menedżer encji, aby można było go natychmiast wygenerować. Tak:

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

Edit:
Jak podkreślił Geoff będzie odłączyć tylko ostatnią utworzony obsługi obiektu. Dlatego ta metoda jest zalecana jako , a nie.

+1

To oddzieliłoby tylko ostatniego użytkownika, a nie 19, który to zrobił - popraw mnie, jeśli się mylę. –

+0

@Geoff cholera, myślę, że masz rację. Zmodyfikuje moją odpowiedź. –

0

Inną alternatywą jest merge rola powrotem po jasne:

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

Nie jestem pewien, jak drogie merge() jest - gdybym miał zgadywać, pójdę z sugestią Arnaud dnia użycie getReference()

+0

dzięki, spróbuję też tego – bazo