DDC-2409: Merge operation tries to add new detached entities to indentity map and load them as proxies #3122

Closed
doctrinebot opened this Issue Apr 22, 2013 · 3 comments

1 participant

@doctrinebot

Jira issue originally created by user deatheriam:

class A
    {
       /****
        *  @ORM\ManyToOne(targetEntity= "B"...
        *  @ORM\JoinColumn(name=" ...
        */
        protected $b;

        public function getB()
        {
            return $this->b;
        }

        public function setB($b)
        {
            $this->b = $b;
        }
}

    class B
    {
       /****
        * As
        *
        * @var \Doctrine\Common\Collections\Collection
        *
        * @ORM\OneToMany(targetEntity="A", mappedBy="B")
        */
        protected $As;
    }

    $b = new \B();

    $a = $em->find('A', 123);

    $a->setB($b);

    $em->detach($a);

    $em->detach($b);

    $b = $em->merge($b); // notice that $b now is merged

    $a = $em->merge($a); //  hangs as it creates the proxy for $b and tries to load a though **load even though $b is already managed

Couple of possible issues in the following code from doMerge:

if ($assoc2['type'] & ClassMetadata::TO_ONE) {
                        $other = $prop->getValue($entity);
                        if ($other === null) {
                            $prop->setValue($managedCopy, null);
                        } else if ($other instanceof Proxy && !$other->*_isInitialized_*) {
                            // do not merge fields marked lazy that have not been fetched.
                            continue;
                        } else if ( ! $assoc2['isCascadeMerge']) {
                            if ($this->getEntityState($other, self::STATE*DETACHED) !== self::STATE*MANAGED) {
                                $targetClass = $this->em->getClassMetadata($assoc2['targetEntity']);
                                $relatedId = $targetClass->getIdentifierValues($other);

                                if ($targetClass->subClasses) {
                                    $other = $this->em->find($targetClass->name, $relatedId);
                                } else {
                                    $other = $this->em->getProxyFactory()->getProxy($assoc2['targetEntity'], $relatedId);
                                    $this->registerManaged($other, $relatedId, array());
                                }
                            }
                            $prop->setValue($managedCopy, $other);
                        }
     $relatedId = $targetClass->getIdentifierValues($other);

$relatedId is emply as the detached $other was never flushed. It should never be used to add this entity to the identityMap ($this->registerManaged($other, $relatedId, array());)

$other = $this->em->getProxyFactory()->getProxy($assoc2['targetEntity'], $relatedId);

This should never use the proxy factory for new detached entities as they are already merged back ($b). This method seems to not have any means to find managed $b.

If $b = $em->merge($b); was not called, the method would probably have worked but I think it is not right to rely on that calling or not calling certain methods or their order.

@doctrinebot

Comment created by @beberlei:

Merged Fabios Pull Request

@doctrinebot

Issue was closed with resolution "Fixed"

@doctrinebot

Comment created by deatheriam:

#655

@doctrinebot doctrinebot added this to the 2.3.4 milestone Dec 6, 2015
@doctrinebot doctrinebot closed this Dec 6, 2015
@doctrinebot doctrinebot added the Bug label Dec 7, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment