Skip to content

Loading…

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

Closed
doctrinebot opened this Issue · 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
@doctrinebot doctrinebot closed this
@doctrinebot doctrinebot added the Bug label
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.