Doctrine 2 - ORM
  1. Doctrine 2 - ORM
  2. DDC-518

Merging an entity with a one to one association to a MANAGED entity with no id throws 'The given entity has no identity.'

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Critical Critical
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 2.0-BETA3
    • Component/s: ORM
    • Security Level: All
    • Labels:
      None

      Description

      Calling merge($entity) where $entity has a one to one association to another entity that has been persisted but not yet flushed (when using auto-generated ids) throws 'The given entity has no identity.'

      It looks like it does this because _doMerge in UnitOfWork assumes for one to one associations only that the associated entity has an id and calls registerManaged, which then calls addToIdentityMap)on it.

      I think that registeredManaged should only be called if !isset($this->_entityInsertions[spl_object_hash($other)])

      Reproduce.php
      // This is a new element
      $doctor = new \vo\Doctor(); $d1->name = "New doctor";
      
      // This is a detached element which is in the database
      $patient = new \vo\Patient(); $p1->name = "Existing patient"; $p1->id = 1;
      
      $doctor->patients->add($patient);
      $patient ->doctor = $doctor;
      
      $em->persist($doctor);
      
      // This throws InvalidArgumentException: The given entity has no identity. in D:\Projects\ORM\flextrine2\flextrine\web\lib\Doctrine\ORM\UnitOfWork.php on line 1014
      $em->merge($patient);
      
      Doctor.php
      class Doctor {
      
          /** @Id @Column(type="integer") @GeneratedValue(strategy="IDENTITY") */
          public $id;
      	
          /** @Column(length=100, type="string") */
          public $name;
      	
      	/**
           * @OneToMany(targetEntity="Patient", mappedBy="doctor", fetch="EAGER")
           */
      	public $patients;
      	
      	public function __construct() {
      		$this->patients = new ArrayCollection();
      	}
      	
      }
      
      Patient.php
      class Patient {
      	
      	var $_explicitType = "vo/Patient";
      	
          /** @Id @Column(type="integer") @GeneratedValue(strategy="IDENTITY") */
          public $id;
      	
          /** @Column(length=100, type="string") */
          public $name;
      
      	/**
           * @OneToOne(targetEntity="Doctor", inversedBy="patients")
      	 * @JoinColumn(name="doctor_id", referencedColumnName="id")
           */
      	public $doctor;
      	
      }
      
      1. ddc518.patch
        3 kB
        Benjamin Eberlei

        Activity

        Dave Keen created issue -
        Dave Keen made changes -
        Field Original Value New Value
        Summary Merging an entity with a one to one association to a NEW entity throws 'The given entity has no identity.' Merging an entity with a one to one association to a MANAGED entity with no id throws 'The given entity has no identity.'
        Description Calling merge($entity) where $entity has a one to one association to another entity that has been persisted but not yet flushed (when using auto-generated ids) throws 'The given entity has no identity.'

        It looks like it does this because _doMerge in UnitOfWork assumes (for one to one associations only) that the mapped entity has an id and calls registerManaged, which then calls addToIdentityMap)on it.

        I think that registeredManaged should only be called if isset($this->_entityIdentifiers[$mappedEntityOid]), the same as in scheduleForInsert.

        --------------------------------------------------------
        Code to reproduce
        --------------------------------------------------------
        // This is a new element
        $doctor = new \vo\Doctor(); $d1->name = "New doctor";

        // This is a detached element which is in the database
        $patient = new \vo\Patient(); $p1->name = "Existing patient"; $p1->id = 1;

        $doctor->patients->add($patient);
        $patient ->doctor = $doctor;

        $em->persist($doctor);

        // This throws InvalidArgumentException: The given entity has no identity. in D:\Projects\ORM\flextrine2\flextrine\web\lib\Doctrine\ORM\UnitOfWork.php on line 1014
        $em->merge($patient);

        --------------------------------------------------------
        Doctor.php
        --------------------------------------------------------
        class Doctor {

            /** @Id @Column(type="integer") @GeneratedValue(strategy="IDENTITY") */
            public $id;

            /** @Column(length=100, type="string") */
            public $name;

        /**
             * @OneToMany(targetEntity="Patient", mappedBy="doctor", fetch="EAGER")
             */
        public $patients;

        public function __construct() {
        $this->patients = new ArrayCollection();
        }

        }

        --------------------------------------------------------
        Patient.php
        --------------------------------------------------------
        class Patient {

        var $_explicitType = "vo/Patient";

            /** @Id @Column(type="integer") @GeneratedValue(strategy="IDENTITY") */
            public $id;

            /** @Column(length=100, type="string") */
            public $name;

        /**
             * @OneToOne(targetEntity="Doctor", inversedBy="patients")
        * @JoinColumn(name="doctor_id", referencedColumnName="id")
             */
        public $doctor;

        }
        Calling merge($entity) where $entity has a one to one association to another entity that has been persisted but not yet flushed (when using auto-generated ids) throws 'The given entity has no identity.'

        It looks like it does this because _doMerge in UnitOfWork assumes for one to one associations only that the associated entity has an id and calls registerManaged, which then calls addToIdentityMap)on it.

        I think that registeredManaged should only be called if isset($this->_entityIdentifiers[$mappedEntityOid]), the same as in scheduleForInsert.

        --------------------------------------------------------
        Code to reproduce
        --------------------------------------------------------
        // This is a new element
        $doctor = new \vo\Doctor(); $d1->name = "New doctor";

        // This is a detached element which is in the database
        $patient = new \vo\Patient(); $p1->name = "Existing patient"; $p1->id = 1;

        $doctor->patients->add($patient);
        $patient ->doctor = $doctor;

        $em->persist($doctor);

        // This throws InvalidArgumentException: The given entity has no identity. in D:\Projects\ORM\flextrine2\flextrine\web\lib\Doctrine\ORM\UnitOfWork.php on line 1014
        $em->merge($patient);

        --------------------------------------------------------
        Doctor.php
        --------------------------------------------------------
        class Doctor {

            /** @Id @Column(type="integer") @GeneratedValue(strategy="IDENTITY") */
            public $id;

            /** @Column(length=100, type="string") */
            public $name;

        /**
             * @OneToMany(targetEntity="Patient", mappedBy="doctor", fetch="EAGER")
             */
        public $patients;

        public function __construct() {
        $this->patients = new ArrayCollection();
        }

        }

        --------------------------------------------------------
        Patient.php
        --------------------------------------------------------
        class Patient {

        var $_explicitType = "vo/Patient";

            /** @Id @Column(type="integer") @GeneratedValue(strategy="IDENTITY") */
            public $id;

            /** @Column(length=100, type="string") */
            public $name;

        /**
             * @OneToOne(targetEntity="Doctor", inversedBy="patients")
        * @JoinColumn(name="doctor_id", referencedColumnName="id")
             */
        public $doctor;

        }
        Dave Keen made changes -
        Description Calling merge($entity) where $entity has a one to one association to another entity that has been persisted but not yet flushed (when using auto-generated ids) throws 'The given entity has no identity.'

        It looks like it does this because _doMerge in UnitOfWork assumes for one to one associations only that the associated entity has an id and calls registerManaged, which then calls addToIdentityMap)on it.

        I think that registeredManaged should only be called if isset($this->_entityIdentifiers[$mappedEntityOid]), the same as in scheduleForInsert.

        --------------------------------------------------------
        Code to reproduce
        --------------------------------------------------------
        // This is a new element
        $doctor = new \vo\Doctor(); $d1->name = "New doctor";

        // This is a detached element which is in the database
        $patient = new \vo\Patient(); $p1->name = "Existing patient"; $p1->id = 1;

        $doctor->patients->add($patient);
        $patient ->doctor = $doctor;

        $em->persist($doctor);

        // This throws InvalidArgumentException: The given entity has no identity. in D:\Projects\ORM\flextrine2\flextrine\web\lib\Doctrine\ORM\UnitOfWork.php on line 1014
        $em->merge($patient);

        --------------------------------------------------------
        Doctor.php
        --------------------------------------------------------
        class Doctor {

            /** @Id @Column(type="integer") @GeneratedValue(strategy="IDENTITY") */
            public $id;

            /** @Column(length=100, type="string") */
            public $name;

        /**
             * @OneToMany(targetEntity="Patient", mappedBy="doctor", fetch="EAGER")
             */
        public $patients;

        public function __construct() {
        $this->patients = new ArrayCollection();
        }

        }

        --------------------------------------------------------
        Patient.php
        --------------------------------------------------------
        class Patient {

        var $_explicitType = "vo/Patient";

            /** @Id @Column(type="integer") @GeneratedValue(strategy="IDENTITY") */
            public $id;

            /** @Column(length=100, type="string") */
            public $name;

        /**
             * @OneToOne(targetEntity="Doctor", inversedBy="patients")
        * @JoinColumn(name="doctor_id", referencedColumnName="id")
             */
        public $doctor;

        }
        Calling merge($entity) where $entity has a one to one association to another entity that has been persisted but not yet flushed (when using auto-generated ids) throws 'The given entity has no identity.'

        It looks like it does this because _doMerge in UnitOfWork assumes for one to one associations only that the associated entity has an id and calls registerManaged, which then calls addToIdentityMap)on it.

        I think that registeredManaged should only be called if isset($this->_entityIdentifiers[$mappedEntityOid]), the same as in scheduleForInsert.

        --------------------------------------------------------
        Code to reproduce
        --------------------------------------------------------
        {code:title=Reproduce.php|borderStyle=solid}
        // This is a new element
        $doctor = new \vo\Doctor(); $d1->name = "New doctor";

        // This is a detached element which is in the database
        $patient = new \vo\Patient(); $p1->name = "Existing patient"; $p1->id = 1;

        $doctor->patients->add($patient);
        $patient ->doctor = $doctor;

        $em->persist($doctor);

        // This throws InvalidArgumentException: The given entity has no identity. in D:\Projects\ORM\flextrine2\flextrine\web\lib\Doctrine\ORM\UnitOfWork.php on line 1014
        $em->merge($patient);
        {code}

        --------------------------------------------------------
        Doctor.php
        --------------------------------------------------------
        class Doctor {

            /** @Id @Column(type="integer") @GeneratedValue(strategy="IDENTITY") */
            public $id;

            /** @Column(length=100, type="string") */
            public $name;

        /**
             * @OneToMany(targetEntity="Patient", mappedBy="doctor", fetch="EAGER")
             */
        public $patients;

        public function __construct() {
        $this->patients = new ArrayCollection();
        }

        }

        --------------------------------------------------------
        Patient.php
        --------------------------------------------------------
        class Patient {

        var $_explicitType = "vo/Patient";

            /** @Id @Column(type="integer") @GeneratedValue(strategy="IDENTITY") */
            public $id;

            /** @Column(length=100, type="string") */
            public $name;

        /**
             * @OneToOne(targetEntity="Doctor", inversedBy="patients")
        * @JoinColumn(name="doctor_id", referencedColumnName="id")
             */
        public $doctor;

        }
        Dave Keen made changes -
        Description Calling merge($entity) where $entity has a one to one association to another entity that has been persisted but not yet flushed (when using auto-generated ids) throws 'The given entity has no identity.'

        It looks like it does this because _doMerge in UnitOfWork assumes for one to one associations only that the associated entity has an id and calls registerManaged, which then calls addToIdentityMap)on it.

        I think that registeredManaged should only be called if isset($this->_entityIdentifiers[$mappedEntityOid]), the same as in scheduleForInsert.

        --------------------------------------------------------
        Code to reproduce
        --------------------------------------------------------
        {code:title=Reproduce.php|borderStyle=solid}
        // This is a new element
        $doctor = new \vo\Doctor(); $d1->name = "New doctor";

        // This is a detached element which is in the database
        $patient = new \vo\Patient(); $p1->name = "Existing patient"; $p1->id = 1;

        $doctor->patients->add($patient);
        $patient ->doctor = $doctor;

        $em->persist($doctor);

        // This throws InvalidArgumentException: The given entity has no identity. in D:\Projects\ORM\flextrine2\flextrine\web\lib\Doctrine\ORM\UnitOfWork.php on line 1014
        $em->merge($patient);
        {code}

        --------------------------------------------------------
        Doctor.php
        --------------------------------------------------------
        class Doctor {

            /** @Id @Column(type="integer") @GeneratedValue(strategy="IDENTITY") */
            public $id;

            /** @Column(length=100, type="string") */
            public $name;

        /**
             * @OneToMany(targetEntity="Patient", mappedBy="doctor", fetch="EAGER")
             */
        public $patients;

        public function __construct() {
        $this->patients = new ArrayCollection();
        }

        }

        --------------------------------------------------------
        Patient.php
        --------------------------------------------------------
        class Patient {

        var $_explicitType = "vo/Patient";

            /** @Id @Column(type="integer") @GeneratedValue(strategy="IDENTITY") */
            public $id;

            /** @Column(length=100, type="string") */
            public $name;

        /**
             * @OneToOne(targetEntity="Doctor", inversedBy="patients")
        * @JoinColumn(name="doctor_id", referencedColumnName="id")
             */
        public $doctor;

        }
        Calling merge($entity) where $entity has a one to one association to another entity that has been persisted but not yet flushed (when using auto-generated ids) throws 'The given entity has no identity.'

        It looks like it does this because _doMerge in UnitOfWork assumes for one to one associations only that the associated entity has an id and calls registerManaged, which then calls addToIdentityMap)on it.

        I think that registeredManaged should only be called if isset($this->_entityIdentifiers[$mappedEntityOid]), the same as in scheduleForInsert.

        {code:title=Reproduce.php|borderStyle=solid}
        // This is a new element
        $doctor = new \vo\Doctor(); $d1->name = "New doctor";

        // This is a detached element which is in the database
        $patient = new \vo\Patient(); $p1->name = "Existing patient"; $p1->id = 1;

        $doctor->patients->add($patient);
        $patient ->doctor = $doctor;

        $em->persist($doctor);

        // This throws InvalidArgumentException: The given entity has no identity. in D:\Projects\ORM\flextrine2\flextrine\web\lib\Doctrine\ORM\UnitOfWork.php on line 1014
        $em->merge($patient);
        {code}

        {code:title=Doctor.php|borderStyle=solid}
        class Doctor {

            /** @Id @Column(type="integer") @GeneratedValue(strategy="IDENTITY") */
            public $id;

            /** @Column(length=100, type="string") */
            public $name;

        /**
             * @OneToMany(targetEntity="Patient", mappedBy="doctor", fetch="EAGER")
             */
        public $patients;

        public function __construct() {
        $this->patients = new ArrayCollection();
        }

        }
        {code}

        {code:title=Patient.php|borderStyle=solid}
        class Patient {

        var $_explicitType = "vo/Patient";

            /** @Id @Column(type="integer") @GeneratedValue(strategy="IDENTITY") */
            public $id;

            /** @Column(length=100, type="string") */
            public $name;

        /**
             * @OneToOne(targetEntity="Doctor", inversedBy="patients")
        * @JoinColumn(name="doctor_id", referencedColumnName="id")
             */
        public $doctor;

        }
        {code}
        Dave Keen made changes -
        Description Calling merge($entity) where $entity has a one to one association to another entity that has been persisted but not yet flushed (when using auto-generated ids) throws 'The given entity has no identity.'

        It looks like it does this because _doMerge in UnitOfWork assumes for one to one associations only that the associated entity has an id and calls registerManaged, which then calls addToIdentityMap)on it.

        I think that registeredManaged should only be called if isset($this->_entityIdentifiers[$mappedEntityOid]), the same as in scheduleForInsert.

        {code:title=Reproduce.php|borderStyle=solid}
        // This is a new element
        $doctor = new \vo\Doctor(); $d1->name = "New doctor";

        // This is a detached element which is in the database
        $patient = new \vo\Patient(); $p1->name = "Existing patient"; $p1->id = 1;

        $doctor->patients->add($patient);
        $patient ->doctor = $doctor;

        $em->persist($doctor);

        // This throws InvalidArgumentException: The given entity has no identity. in D:\Projects\ORM\flextrine2\flextrine\web\lib\Doctrine\ORM\UnitOfWork.php on line 1014
        $em->merge($patient);
        {code}

        {code:title=Doctor.php|borderStyle=solid}
        class Doctor {

            /** @Id @Column(type="integer") @GeneratedValue(strategy="IDENTITY") */
            public $id;

            /** @Column(length=100, type="string") */
            public $name;

        /**
             * @OneToMany(targetEntity="Patient", mappedBy="doctor", fetch="EAGER")
             */
        public $patients;

        public function __construct() {
        $this->patients = new ArrayCollection();
        }

        }
        {code}

        {code:title=Patient.php|borderStyle=solid}
        class Patient {

        var $_explicitType = "vo/Patient";

            /** @Id @Column(type="integer") @GeneratedValue(strategy="IDENTITY") */
            public $id;

            /** @Column(length=100, type="string") */
            public $name;

        /**
             * @OneToOne(targetEntity="Doctor", inversedBy="patients")
        * @JoinColumn(name="doctor_id", referencedColumnName="id")
             */
        public $doctor;

        }
        {code}
        Calling merge($entity) where $entity has a one to one association to another entity that has been persisted but not yet flushed (when using auto-generated ids) throws 'The given entity has no identity.'

        It looks like it does this because _doMerge in UnitOfWork assumes for one to one associations only that the associated entity has an id and calls registerManaged, which then calls addToIdentityMap)on it.

        I think that registeredManaged should only be called if isset($this->_entityIdentifiers[$mappedEntityOid]), the same as in scheduleForInsert.

        {code:title=Reproduce.php}
        // This is a new element
        $doctor = new \vo\Doctor(); $d1->name = "New doctor";

        // This is a detached element which is in the database
        $patient = new \vo\Patient(); $p1->name = "Existing patient"; $p1->id = 1;

        $doctor->patients->add($patient);
        $patient ->doctor = $doctor;

        $em->persist($doctor);

        // This throws InvalidArgumentException: The given entity has no identity. in D:\Projects\ORM\flextrine2\flextrine\web\lib\Doctrine\ORM\UnitOfWork.php on line 1014
        $em->merge($patient);
        {code}

        {code:title=Doctor.php|borderStyle=solid}
        class Doctor {

            /** @Id @Column(type="integer") @GeneratedValue(strategy="IDENTITY") */
            public $id;

            /** @Column(length=100, type="string") */
            public $name;

        /**
             * @OneToMany(targetEntity="Patient", mappedBy="doctor", fetch="EAGER")
             */
        public $patients;

        public function __construct() {
        $this->patients = new ArrayCollection();
        }

        }
        {code}

        {code:title=Patient.php|borderStyle=solid}
        class Patient {

        var $_explicitType = "vo/Patient";

            /** @Id @Column(type="integer") @GeneratedValue(strategy="IDENTITY") */
            public $id;

            /** @Column(length=100, type="string") */
            public $name;

        /**
             * @OneToOne(targetEntity="Doctor", inversedBy="patients")
        * @JoinColumn(name="doctor_id", referencedColumnName="id")
             */
        public $doctor;

        }
        {code}
        Dave Keen made changes -
        Description Calling merge($entity) where $entity has a one to one association to another entity that has been persisted but not yet flushed (when using auto-generated ids) throws 'The given entity has no identity.'

        It looks like it does this because _doMerge in UnitOfWork assumes for one to one associations only that the associated entity has an id and calls registerManaged, which then calls addToIdentityMap)on it.

        I think that registeredManaged should only be called if isset($this->_entityIdentifiers[$mappedEntityOid]), the same as in scheduleForInsert.

        {code:title=Reproduce.php}
        // This is a new element
        $doctor = new \vo\Doctor(); $d1->name = "New doctor";

        // This is a detached element which is in the database
        $patient = new \vo\Patient(); $p1->name = "Existing patient"; $p1->id = 1;

        $doctor->patients->add($patient);
        $patient ->doctor = $doctor;

        $em->persist($doctor);

        // This throws InvalidArgumentException: The given entity has no identity. in D:\Projects\ORM\flextrine2\flextrine\web\lib\Doctrine\ORM\UnitOfWork.php on line 1014
        $em->merge($patient);
        {code}

        {code:title=Doctor.php|borderStyle=solid}
        class Doctor {

            /** @Id @Column(type="integer") @GeneratedValue(strategy="IDENTITY") */
            public $id;

            /** @Column(length=100, type="string") */
            public $name;

        /**
             * @OneToMany(targetEntity="Patient", mappedBy="doctor", fetch="EAGER")
             */
        public $patients;

        public function __construct() {
        $this->patients = new ArrayCollection();
        }

        }
        {code}

        {code:title=Patient.php|borderStyle=solid}
        class Patient {

        var $_explicitType = "vo/Patient";

            /** @Id @Column(type="integer") @GeneratedValue(strategy="IDENTITY") */
            public $id;

            /** @Column(length=100, type="string") */
            public $name;

        /**
             * @OneToOne(targetEntity="Doctor", inversedBy="patients")
        * @JoinColumn(name="doctor_id", referencedColumnName="id")
             */
        public $doctor;

        }
        {code}
        Calling merge($entity) where $entity has a one to one association to another entity that has been persisted but not yet flushed (when using auto-generated ids) throws 'The given entity has no identity.'

        It looks like it does this because _doMerge in UnitOfWork assumes for one to one associations only that the associated entity has an id and calls registerManaged, which then calls addToIdentityMap)on it.

        I think that registeredManaged should only be called if isset($this->_entityIdentifiers[$mappedEntityOid]), the same as in scheduleForInsert.

        {code:title=Reproduce.php}
        // This is a new element
        $doctor = new \vo\Doctor(); $d1->name = "New doctor";

        // This is a detached element which is in the database
        $patient = new \vo\Patient(); $p1->name = "Existing patient"; $p1->id = 1;

        $doctor->patients->add($patient);
        $patient ->doctor = $doctor;

        $em->persist($doctor);

        // This throws InvalidArgumentException: The given entity has no identity. in D:\Projects\ORM\flextrine2\flextrine\web\lib\Doctrine\ORM\UnitOfWork.php on line 1014
        $em->merge($patient);
        {code}

        {code:title=Doctor.php}
        class Doctor {

            /** @Id @Column(type="integer") @GeneratedValue(strategy="IDENTITY") */
            public $id;

            /** @Column(length=100, type="string") */
            public $name;

        /**
             * @OneToMany(targetEntity="Patient", mappedBy="doctor", fetch="EAGER")
             */
        public $patients;

        public function __construct() {
        $this->patients = new ArrayCollection();
        }

        }
        {code}

        {code:title=Patient.php}
        class Patient {

        var $_explicitType = "vo/Patient";

            /** @Id @Column(type="integer") @GeneratedValue(strategy="IDENTITY") */
            public $id;

            /** @Column(length=100, type="string") */
            public $name;

        /**
             * @OneToOne(targetEntity="Doctor", inversedBy="patients")
        * @JoinColumn(name="doctor_id", referencedColumnName="id")
             */
        public $doctor;

        }
        {code}
        Dave Keen made changes -
        Description Calling merge($entity) where $entity has a one to one association to another entity that has been persisted but not yet flushed (when using auto-generated ids) throws 'The given entity has no identity.'

        It looks like it does this because _doMerge in UnitOfWork assumes for one to one associations only that the associated entity has an id and calls registerManaged, which then calls addToIdentityMap)on it.

        I think that registeredManaged should only be called if isset($this->_entityIdentifiers[$mappedEntityOid]), the same as in scheduleForInsert.

        {code:title=Reproduce.php}
        // This is a new element
        $doctor = new \vo\Doctor(); $d1->name = "New doctor";

        // This is a detached element which is in the database
        $patient = new \vo\Patient(); $p1->name = "Existing patient"; $p1->id = 1;

        $doctor->patients->add($patient);
        $patient ->doctor = $doctor;

        $em->persist($doctor);

        // This throws InvalidArgumentException: The given entity has no identity. in D:\Projects\ORM\flextrine2\flextrine\web\lib\Doctrine\ORM\UnitOfWork.php on line 1014
        $em->merge($patient);
        {code}

        {code:title=Doctor.php}
        class Doctor {

            /** @Id @Column(type="integer") @GeneratedValue(strategy="IDENTITY") */
            public $id;

            /** @Column(length=100, type="string") */
            public $name;

        /**
             * @OneToMany(targetEntity="Patient", mappedBy="doctor", fetch="EAGER")
             */
        public $patients;

        public function __construct() {
        $this->patients = new ArrayCollection();
        }

        }
        {code}

        {code:title=Patient.php}
        class Patient {

        var $_explicitType = "vo/Patient";

            /** @Id @Column(type="integer") @GeneratedValue(strategy="IDENTITY") */
            public $id;

            /** @Column(length=100, type="string") */
            public $name;

        /**
             * @OneToOne(targetEntity="Doctor", inversedBy="patients")
        * @JoinColumn(name="doctor_id", referencedColumnName="id")
             */
        public $doctor;

        }
        {code}
        Calling merge($entity) where $entity has a one to one association to another entity that has been persisted but not yet flushed (when using auto-generated ids) throws 'The given entity has no identity.'

        It looks like it does this because _doMerge in UnitOfWork assumes for one to one associations only that the associated entity has an id and calls registerManaged, which then calls addToIdentityMap)on it.

        I think that registeredManaged should only be called if isset($this->_entityIdentifiers[spl_object_hash($other)]).

        {code:title=Reproduce.php}
        // This is a new element
        $doctor = new \vo\Doctor(); $d1->name = "New doctor";

        // This is a detached element which is in the database
        $patient = new \vo\Patient(); $p1->name = "Existing patient"; $p1->id = 1;

        $doctor->patients->add($patient);
        $patient ->doctor = $doctor;

        $em->persist($doctor);

        // This throws InvalidArgumentException: The given entity has no identity. in D:\Projects\ORM\flextrine2\flextrine\web\lib\Doctrine\ORM\UnitOfWork.php on line 1014
        $em->merge($patient);
        {code}

        {code:title=Doctor.php}
        class Doctor {

            /** @Id @Column(type="integer") @GeneratedValue(strategy="IDENTITY") */
            public $id;

            /** @Column(length=100, type="string") */
            public $name;

        /**
             * @OneToMany(targetEntity="Patient", mappedBy="doctor", fetch="EAGER")
             */
        public $patients;

        public function __construct() {
        $this->patients = new ArrayCollection();
        }

        }
        {code}

        {code:title=Patient.php}
        class Patient {

        var $_explicitType = "vo/Patient";

            /** @Id @Column(type="integer") @GeneratedValue(strategy="IDENTITY") */
            public $id;

            /** @Column(length=100, type="string") */
            public $name;

        /**
             * @OneToOne(targetEntity="Doctor", inversedBy="patients")
        * @JoinColumn(name="doctor_id", referencedColumnName="id")
             */
        public $doctor;

        }
        {code}
        Dave Keen made changes -
        Description Calling merge($entity) where $entity has a one to one association to another entity that has been persisted but not yet flushed (when using auto-generated ids) throws 'The given entity has no identity.'

        It looks like it does this because _doMerge in UnitOfWork assumes for one to one associations only that the associated entity has an id and calls registerManaged, which then calls addToIdentityMap)on it.

        I think that registeredManaged should only be called if isset($this->_entityIdentifiers[spl_object_hash($other)]).

        {code:title=Reproduce.php}
        // This is a new element
        $doctor = new \vo\Doctor(); $d1->name = "New doctor";

        // This is a detached element which is in the database
        $patient = new \vo\Patient(); $p1->name = "Existing patient"; $p1->id = 1;

        $doctor->patients->add($patient);
        $patient ->doctor = $doctor;

        $em->persist($doctor);

        // This throws InvalidArgumentException: The given entity has no identity. in D:\Projects\ORM\flextrine2\flextrine\web\lib\Doctrine\ORM\UnitOfWork.php on line 1014
        $em->merge($patient);
        {code}

        {code:title=Doctor.php}
        class Doctor {

            /** @Id @Column(type="integer") @GeneratedValue(strategy="IDENTITY") */
            public $id;

            /** @Column(length=100, type="string") */
            public $name;

        /**
             * @OneToMany(targetEntity="Patient", mappedBy="doctor", fetch="EAGER")
             */
        public $patients;

        public function __construct() {
        $this->patients = new ArrayCollection();
        }

        }
        {code}

        {code:title=Patient.php}
        class Patient {

        var $_explicitType = "vo/Patient";

            /** @Id @Column(type="integer") @GeneratedValue(strategy="IDENTITY") */
            public $id;

            /** @Column(length=100, type="string") */
            public $name;

        /**
             * @OneToOne(targetEntity="Doctor", inversedBy="patients")
        * @JoinColumn(name="doctor_id", referencedColumnName="id")
             */
        public $doctor;

        }
        {code}
        Calling merge($entity) where $entity has a one to one association to another entity that has been persisted but not yet flushed (when using auto-generated ids) throws 'The given entity has no identity.'

        It looks like it does this because _doMerge in UnitOfWork assumes for one to one associations only that the associated entity has an id and calls registerManaged, which then calls addToIdentityMap)on it.

        I think that registeredManaged should only be called if !isset($this->_entityIdentifiers[spl_object_hash($other)]).

        {code:title=Reproduce.php}
        // This is a new element
        $doctor = new \vo\Doctor(); $d1->name = "New doctor";

        // This is a detached element which is in the database
        $patient = new \vo\Patient(); $p1->name = "Existing patient"; $p1->id = 1;

        $doctor->patients->add($patient);
        $patient ->doctor = $doctor;

        $em->persist($doctor);

        // This throws InvalidArgumentException: The given entity has no identity. in D:\Projects\ORM\flextrine2\flextrine\web\lib\Doctrine\ORM\UnitOfWork.php on line 1014
        $em->merge($patient);
        {code}

        {code:title=Doctor.php}
        class Doctor {

            /** @Id @Column(type="integer") @GeneratedValue(strategy="IDENTITY") */
            public $id;

            /** @Column(length=100, type="string") */
            public $name;

        /**
             * @OneToMany(targetEntity="Patient", mappedBy="doctor", fetch="EAGER")
             */
        public $patients;

        public function __construct() {
        $this->patients = new ArrayCollection();
        }

        }
        {code}

        {code:title=Patient.php}
        class Patient {

        var $_explicitType = "vo/Patient";

            /** @Id @Column(type="integer") @GeneratedValue(strategy="IDENTITY") */
            public $id;

            /** @Column(length=100, type="string") */
            public $name;

        /**
             * @OneToOne(targetEntity="Doctor", inversedBy="patients")
        * @JoinColumn(name="doctor_id", referencedColumnName="id")
             */
        public $doctor;

        }
        {code}
        Dave Keen made changes -
        Description Calling merge($entity) where $entity has a one to one association to another entity that has been persisted but not yet flushed (when using auto-generated ids) throws 'The given entity has no identity.'

        It looks like it does this because _doMerge in UnitOfWork assumes for one to one associations only that the associated entity has an id and calls registerManaged, which then calls addToIdentityMap)on it.

        I think that registeredManaged should only be called if !isset($this->_entityIdentifiers[spl_object_hash($other)]).

        {code:title=Reproduce.php}
        // This is a new element
        $doctor = new \vo\Doctor(); $d1->name = "New doctor";

        // This is a detached element which is in the database
        $patient = new \vo\Patient(); $p1->name = "Existing patient"; $p1->id = 1;

        $doctor->patients->add($patient);
        $patient ->doctor = $doctor;

        $em->persist($doctor);

        // This throws InvalidArgumentException: The given entity has no identity. in D:\Projects\ORM\flextrine2\flextrine\web\lib\Doctrine\ORM\UnitOfWork.php on line 1014
        $em->merge($patient);
        {code}

        {code:title=Doctor.php}
        class Doctor {

            /** @Id @Column(type="integer") @GeneratedValue(strategy="IDENTITY") */
            public $id;

            /** @Column(length=100, type="string") */
            public $name;

        /**
             * @OneToMany(targetEntity="Patient", mappedBy="doctor", fetch="EAGER")
             */
        public $patients;

        public function __construct() {
        $this->patients = new ArrayCollection();
        }

        }
        {code}

        {code:title=Patient.php}
        class Patient {

        var $_explicitType = "vo/Patient";

            /** @Id @Column(type="integer") @GeneratedValue(strategy="IDENTITY") */
            public $id;

            /** @Column(length=100, type="string") */
            public $name;

        /**
             * @OneToOne(targetEntity="Doctor", inversedBy="patients")
        * @JoinColumn(name="doctor_id", referencedColumnName="id")
             */
        public $doctor;

        }
        {code}
        Calling merge($entity) where $entity has a one to one association to another entity that has been persisted but not yet flushed (when using auto-generated ids) throws 'The given entity has no identity.'

        It looks like it does this because _doMerge in UnitOfWork assumes for one to one associations only that the associated entity has an id and calls registerManaged, which then calls addToIdentityMap)on it.

        I think that registeredManaged should only be called if !isset($this->_entityInsertions[spl_object_hash($other)])

        {code:title=Reproduce.php}
        // This is a new element
        $doctor = new \vo\Doctor(); $d1->name = "New doctor";

        // This is a detached element which is in the database
        $patient = new \vo\Patient(); $p1->name = "Existing patient"; $p1->id = 1;

        $doctor->patients->add($patient);
        $patient ->doctor = $doctor;

        $em->persist($doctor);

        // This throws InvalidArgumentException: The given entity has no identity. in D:\Projects\ORM\flextrine2\flextrine\web\lib\Doctrine\ORM\UnitOfWork.php on line 1014
        $em->merge($patient);
        {code}

        {code:title=Doctor.php}
        class Doctor {

            /** @Id @Column(type="integer") @GeneratedValue(strategy="IDENTITY") */
            public $id;

            /** @Column(length=100, type="string") */
            public $name;

        /**
             * @OneToMany(targetEntity="Patient", mappedBy="doctor", fetch="EAGER")
             */
        public $patients;

        public function __construct() {
        $this->patients = new ArrayCollection();
        }

        }
        {code}

        {code:title=Patient.php}
        class Patient {

        var $_explicitType = "vo/Patient";

            /** @Id @Column(type="integer") @GeneratedValue(strategy="IDENTITY") */
            public $id;

            /** @Column(length=100, type="string") */
            public $name;

        /**
             * @OneToOne(targetEntity="Doctor", inversedBy="patients")
        * @JoinColumn(name="doctor_id", referencedColumnName="id")
             */
        public $doctor;

        }
        {code}
        Roman S. Borschel made changes -
        Fix Version/s 2.0-BETA2 [ 10050 ]
        Roman S. Borschel made changes -
        Priority Major [ 3 ] Critical [ 2 ]
        Benjamin Eberlei made changes -
        Fix Version/s 2.0-BETA3 [ 10060 ]
        Fix Version/s 2.0-BETA2 [ 10050 ]
        Benjamin Eberlei made changes -
        Attachment ddc518.patch [ 10629 ]
        Roman S. Borschel made changes -
        Status Open [ 1 ] In Progress [ 3 ]
        Roman S. Borschel made changes -
        Status In Progress [ 3 ] Closed [ 6 ]
        Resolution Fixed [ 1 ]
        Benjamin Eberlei made changes -
        Workflow jira [ 11216 ] jira-feedback [ 15615 ]
        Benjamin Eberlei made changes -
        Workflow jira-feedback [ 15615 ] jira-feedback2 [ 17479 ]
        Benjamin Eberlei made changes -
        Workflow jira-feedback2 [ 17479 ] jira-feedback3 [ 19736 ]

          People

          • Assignee:
            Roman S. Borschel
            Reporter:
            Dave Keen
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: