I have a script which saves some new entities of type "A" in the loop to the database. But the loop can throw some exceptions which close entityManager. So it must be reopen. It causes that another entity of type "B" which should be joined with every "A" entity is detached from unitOfWork. How can I attache "B" to unitOfWork? This is an example:
public function insert( Array $items )
{
$B = $this->bRepository->findOneBy( ['name' => 'blog'] );
$result = [ 'errors' => [], 'saved_items' => [] ];
foreach( $items as $item )
{
try
{
$A = new Entity\A();
$A->create([
'name' => $item->name,
'B' => $B // Here is the problem after exception. $B is detached.
]);
$this->em->persist( $A );
$this->em->flush( $A );
$result['saved_items'][] = $item->name;
} catch( \Eception $e )
{
$result['errors'][] = 'Item ' . $item->name . ' was not saved.';
$this->em = $this->em->create( $this->em->getConnection(), $this->em->getConfiguration() );
}
}
return $result;
}
I tried $this->em->persist($B)
but it makes me a duplicates of $B in database. It means new B items in DB(with new ids) instead of creating join between A and B. I also tried $this->em->merge($B)
but it throws an exception "A new entity was found through the relationship 'App\Model\Entity\A#B' that was not configured to cascade persist operations". How to handle this issue?
Thanks a lot.
An entity can become detached when the Session used to load it was closed, or when we call Session. evict(entity) or Session. clear(). For reference on both Session.
A detached entity (a.k.a. a detached object) is an object that has the same ID as an entity in the persistence store but that is no longer part of a persistence context (the scope of an EntityManager session).
Persist and flush flush() . em. persist(entity, flush?: boolean) is used to mark new entities for future persisting. It will make the entity managed by given EntityManager and once flush will be called, it will be written to the database.
Doctrine uses the Identity Map pattern to track objects. Whenever you fetch an object from the database, Doctrine will keep a reference to this object inside its UnitOfWork. The array holding all the entity references is two-levels deep and has the keys root entity name and id.
So it seems if something is merged like $B entity in this case, it is necessary to assign it via = operator. Because merge() RETURNS entity. It does not affect original entity.
catch( \Exception $e )
{
...
$B = $this->em->merge( $B );
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With