Doctrine 2: strange behavior when inserting batch processing of objects that reference other objects

I am trying to describe the batch processing method described here: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/batch-processing.html

my code is as follows

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

the problem is that after the first call to em-> flush () the $ role is also disabled, and for every 20 users a new role with a new identifier is created, which is not what I want

Is there any workaround for this situation? the only one I could do is get the user role object every time in the loop

thanks

+6
source share
3 answers

clear() separates all entities managed by the entity manager, so $role also disabled, and trying to save a separate object creates a new object.

You should get this role again after cleaning:

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

Or just create a link:

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

As an alternative to arnaud576875 answer, you can disconnect the user $ from the entity manager so that he can be GC'd immediately. For instance:

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

Edit:
As Jeff noted, this will only delete the last created user object. Therefore, this method is not recommended.

+1
source

Another alternative is to merge role back after clear:

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

I'm not sure how expensive merging () is - if I were to guess, I would go with an arnaud suggestion to use getReference ()

0
source

Source: https://habr.com/ru/post/897387/


All Articles