Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to attache detached entity in Doctrine?

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.

like image 724
Čamo Avatar asked Mar 10 '16 19:03

Čamo


People also ask

How do you make an entity detached?

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.

What is a detached entity?

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).

What is persist flush?

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.

How doctrine works?

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.


1 Answers

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 );
}
like image 67
Čamo Avatar answered Sep 22 '22 16:09

Čamo