Details
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;
}
Activity
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 ] |
This list may be incomplete, as errors occurred whilst retrieving source from linked applications:
- Request to http://www.doctrine-project.org/fisheye/ failed: Error in remote call to 'FishEye 0 (http://www.doctrine-project.org/fisheye/)' (http://www.doctrine-project.org/fisheye) [AbstractRestCommand{path='/rest-service-fe/search-v1/crossRepositoryQuery', params={query=DDC-518, expand=changesets[-21:-1].revisions[0:29],reviews}, methodType=GET}] : Received status code 503 (Service Temporarily Unavailable)
I think the order of operations in your example is not correct even though the error is misleading.
You are associating a "new doctor" to a "detached patient". That does not seem right, remember that merge() returns a managed copy, thus when merging the patient later, the "new doctor" is still associated with the "detached patient", not with the managed one.
The following should work: