Doctrine EntityManager cleanup method in nested objects

I would like to use the batch insertion doctrine to optimize the insertion of a large number of objects. The problem is with the Clear method. It says that this method will decouple all entities that the EntityManager manages. So what should I do in a situation where I have a parent Entity that has many children and each child has its own children, for example:

  • riseSession
    • track
      • points

So, I have 1 rideSession, 3 tracks and each track for isntance 2,000 points. I can use batch processing in the last loop, which is responsible for storing points. But if I use the pure method, then how do I set the parents for the glasses and tracks? An open method will separate them, won't it?

+3


source to share


2 answers


You will soon reach your limit of memory. The idea flush()

in batches is ok, but you need clear()

EntityManager

at the end of each batch to free up used memory.

But in your case you will have ORMInvalidArgumentException

(aka "new entity foung via relation") if you call $child->setParent($parent);

after you did $entityManager->clear();

.



The problem is that $parent

it is now in state detached

in UnitOfWork

. Therefore, you need to put it back to the state managed

. This can be done using $entityManager->merge();

or simply using $parentRepository->find($parent->getId());

.

Just make sure that all Entities managed

after each are clear()

displayed in case you intend to use them later.

+4


source


If you have all of your 40,000 objects already loaded into memory, you can just use the code without cleaning up. Object manager cleanup is used to optimize memory in PHP script. If you have enough memory to store all the objects you don't need to delete the object manager altogether.

To optimize memory in this case, you can unset($entity)

after each save.



And to fit the width of the DB connection, you can group multiple objects like in the example.

$batchSize = 20;
for ($i = 1; $i <= 10000; ++$i) {
    $em->persist($entities[$i]);
    unset($entities[$i]);
    if (($i % $batchSize) === 0) {
        $em->flush();
    }
}
$em->flush(); //Persist objects that did not make up an entire batch

      

+1


source







All Articles