[DDC-2409] Merge operation tries to add new detached entities to indentity map and load them as proxies Created: 22/Apr/13  Updated: 05/May/13  Resolved: 01/May/13

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.3.1
Fix Version/s: 2.4, 2.3.4
Security Level: All

Type: Bug Priority: Major
Reporter: Oleg Namaka Assignee: Fabio B. Silva
Resolution: Fixed Votes: 0
Labels: None

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);
	$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.
                        } 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.

Comment by Benjamin Eberlei [ 01/May/13 ]

Merged Fabios Pull Request

Comment by Oleg Namaka [ 01/May/13 ]


Generated at Fri Aug 28 13:20:04 EDT 2015 using JIRA 6.4.10#64025-sha1:5b8b74079161cd76a20ab66dda52747ee6701bd6.