From 72d838a80404591404e710d78329869c2960fd88 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 23 Jan 2014 17:31:08 +0000 Subject: [PATCH 1/8] [DDC-2931] testcase to reproduce Jira 2931 --- .../ORM/Functional/Ticket/DDC2931Test.php | 167 ++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100755 tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2931Test.php diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2931Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2931Test.php new file mode 100755 index 000000000..da98a8d8a --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2931Test.php @@ -0,0 +1,167 @@ +_schemaTool->createSchema(array( + $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC2931User'), + )); + } catch(\Exception $e) { + + } + } + + public function testIssue() + { + $first = new DDC2931User(null); + $this->_em->persist($first); + + $second = new DDC2931User($first); + $this->_em->persist($second); + + $third = new DDC2931User($second); + $this->_em->persist($third); + + + $this->_em->flush(); + $this->_em->clear(); + + // Load Entity in second order + $second = $this->_em->find('Doctrine\Tests\ORM\Functional\Ticket\DDC2931User', $second->getId()); + // crash here with "Segmentation error" caused by infinite loop. This work correctly with doctrine 2.3 + $second->getRank(); + } +} + + +/** + * @Entity + */ +class DDC2931User +{ + + /** + * @Id + * @Column(type="integer") + * @GeneratedValue(strategy="AUTO") + */ + protected $id; + + /** + * + * @OneToOne(targetEntity="DDC2931User", inversedBy="child") + * @JoinColumn(name="parent_id", referencedColumnName="id", nullable = true) + **/ + protected $parent; + + /** + * @OneToOne(targetEntity="DDC2931User", mappedBy="parent") + **/ + protected $child; + + + /** + * Constructeur. + */ + public function __construct ($parent = null) + { + $this->parent = $parent; + } + + /** + * Return Rank recursively + * My rank is 1 + rank of my parent + * @return integer + */ + public function getRank() + { + if($this->parent == null) + return 1; + return 1 + $this->parent->getRank(); + } + + /** + * @return the $id + */ + public function getId () + { + return $this->id; + } + + /** + * @return the $parent + */ + public function getParent () + { + return $this->parent; + } + + + /** + * @param integer $id + */ + public function setId ($id) + { + $this->id = $id; + } + + /** + * @param DDC2931User $parent + */ + public function setParent ($parent) + { + $this->parent = $parent; + } + + + /** + * @return the $child + */ + public function getChild () + { + return $this->child; + } + + /** + * @param DDC2931User $child + */ + public function setChild ($child) + { + $this->child = $child; + } + + /** + * Magic getter to expose protected properties. + * + * @param string $property + * @return mixed + */ + public function __get ($property) + { + return $this->$property; + } + + /** + * Magic setter to save protected properties. + * + * @param string $property + * @param mixed $value + */ + public function __set ($property, $value) + { + $this->$property = $value; + } + +} From 157c79381037ca1d365f07e368595d23e6932941 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Thu, 23 Jan 2014 20:14:22 +0100 Subject: [PATCH 2/8] DDC-2931 - cleaning up code formatting/simplifying test case --- .../ORM/Functional/Ticket/DDC2931Test.php | 163 ++++-------------- 1 file changed, 33 insertions(+), 130 deletions(-) diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2931Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2931Test.php index da98a8d8a..9d7607491 100755 --- a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2931Test.php +++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2931Test.php @@ -2,8 +2,6 @@ namespace Doctrine\Tests\ORM\Functional\Ticket; -use Doctrine\Common\Collections\ArrayCollection; - require_once __DIR__ . '/../../../TestInit.php'; /** @@ -14,154 +12,59 @@ class DDC2931Test extends \Doctrine\Tests\OrmFunctionalTestCase public function setUp() { parent::setUp(); + try { $this->_schemaTool->createSchema(array( $this->_em->getClassMetadata(__NAMESPACE__ . '\DDC2931User'), )); - } catch(\Exception $e) { - + } catch (\Exception $e) { + // no action needed - schema seems to be already in place } } public function testIssue() { - $first = new DDC2931User(null); - $this->_em->persist($first); + $first = new DDC2931User(); + $second = new DDC2931User(); + $third = new DDC2931User(); - $second = new DDC2931User($first); - $this->_em->persist($second); + $second->parent = $first; + $third->parent = $second; - $third = new DDC2931User($second); - $this->_em->persist($third); - - - $this->_em->flush(); - $this->_em->clear(); + $this->_em->persist($first); + $this->_em->persist($second); + $this->_em->persist($third); - // Load Entity in second order - $second = $this->_em->find('Doctrine\Tests\ORM\Functional\Ticket\DDC2931User', $second->getId()); - // crash here with "Segmentation error" caused by infinite loop. This work correctly with doctrine 2.3 - $second->getRank(); + $this->_em->flush(); + $this->_em->clear(); + + // Load Entity in second order + $second = $this->_em->find('Doctrine\Tests\ORM\Functional\Ticket\DDC2931User', $second->id); + $this->assertSame(2, $second->getRank()); } } -/** - * @Entity - */ +/** @Entity */ class DDC2931User { - /** - * @Id - * @Column(type="integer") - * @GeneratedValue(strategy="AUTO") - */ - protected $id; + /** @Id @Column(type="integer") @GeneratedValue(strategy="AUTO") */ + public $id; - /** - * - * @OneToOne(targetEntity="DDC2931User", inversedBy="child") - * @JoinColumn(name="parent_id", referencedColumnName="id", nullable = true) - **/ - protected $parent; + /** @OneToOne(targetEntity="DDC2931User", inversedBy="child") */ + public $parent; - /** - * @OneToOne(targetEntity="DDC2931User", mappedBy="parent") - **/ - protected $child; - - - /** - * Constructeur. - */ - public function __construct ($parent = null) - { - $this->parent = $parent; - } - - /** - * Return Rank recursively - * My rank is 1 + rank of my parent - * @return integer - */ - public function getRank() - { - if($this->parent == null) - return 1; - return 1 + $this->parent->getRank(); - } - - /** - * @return the $id - */ - public function getId () - { - return $this->id; - } - - /** - * @return the $parent - */ - public function getParent () - { - return $this->parent; - } - - - /** - * @param integer $id - */ - public function setId ($id) - { - $this->id = $id; - } - - /** - * @param DDC2931User $parent - */ - public function setParent ($parent) - { - $this->parent = $parent; - } - - - /** - * @return the $child - */ - public function getChild () - { - return $this->child; - } - - /** - * @param DDC2931User $child - */ - public function setChild ($child) - { - $this->child = $child; - } - - /** - * Magic getter to expose protected properties. - * - * @param string $property - * @return mixed - */ - public function __get ($property) - { - return $this->$property; - } - - /** - * Magic setter to save protected properties. - * - * @param string $property - * @param mixed $value - */ - public function __set ($property, $value) - { - $this->$property = $value; - } + /** @OneToOne(targetEntity="DDC2931User", mappedBy="parent") */ + public $child; + /** + * Return Rank recursively + * My rank is 1 + rank of my parent + * @return integer + */ + public function getRank() + { + return 1 + ($this->parent ? $this->parent->getRank() : 0); + } } From f37856829f483393739392a220a8aa8806f44aae Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Fri, 24 Jan 2014 02:43:14 +0100 Subject: [PATCH 3/8] DDC-2931 - Detailed explanation --- .../Tests/ORM/Functional/Ticket/DDC2931Test.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2931Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2931Test.php index 9d7607491..c1b5c613b 100755 --- a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2931Test.php +++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2931Test.php @@ -38,8 +38,18 @@ class DDC2931Test extends \Doctrine\Tests\OrmFunctionalTestCase $this->_em->flush(); $this->_em->clear(); + // After some debugging, I found that the issue came from + // [`UnitOfWork#createEntity`](https://github.com/doctrine/doctrine2/blob/bba5ec27fbbe35224be48878a0c92827ef2f9733/lib/Doctrine/ORM/UnitOfWork.php#L2512-L2528) with #406 (DCOM-96). + // When initializing the proxy for `$first` (during the `DDC2931User#getRank()` call), the ORM attempts to fetch also `$second` again + // via [`ObjectHydrator#getEntity`](https://github.com/doctrine/doctrine2/blob/bba5ec27fbbe35224be48878a0c92827ef2f9733/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php#L280)`, + // but the hint `doctrine.refresh.entity` contains the initialized proxy, while the identifier passed down + // is the identifier of `$second` (not a proxy). + // `UnitOfWork#createQuery` does some comparisons and detects that in fact, the two objects don't correspond, + // and therefore marks the entity as "to be detached" + // Load Entity in second order $second = $this->_em->find('Doctrine\Tests\ORM\Functional\Ticket\DDC2931User', $second->id); + $this->assertSame(2, $second->getRank()); } } @@ -65,6 +75,13 @@ class DDC2931User */ public function getRank() { + //$id = $this->parent->id; + //$hash = spl_object_hash($this); return 1 + ($this->parent ? $this->parent->getRank() : 0); } + + public function __wakeup() + { + echo 'foo'; + } } From 0bc94589e104618c92e569b67283f964b1ff638c Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Fri, 24 Jan 2014 02:45:28 +0100 Subject: [PATCH 4/8] DDC-2931 - Removing refresh hints when fetching association data in hydrators --- .../ORM/Internal/Hydration/ObjectHydrator.php | 69 ++++++++++++++++++- 1 file changed, 67 insertions(+), 2 deletions(-) diff --git a/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php b/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php index fafc497c0..27e256814 100644 --- a/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php +++ b/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php @@ -280,6 +280,71 @@ class ObjectHydrator extends AbstractHydrator return $this->_uow->createEntity($className, $data, $this->_hints); } + /** + * Gets an association entity instance. + * + * @param array $data + * @param string $dqlAlias + * + * @return object The associated entity. + * + * @throws HydrationException + */ + private function getAssociatedEntity(array $data, $dqlAlias) + { + $className = $this->_rsm->aliasMap[$dqlAlias]; + + if (isset($this->_rsm->discriminatorColumns[$dqlAlias])) { + if ( ! isset($this->_rsm->metaMappings[$this->_rsm->discriminatorColumns[$dqlAlias]])) { + throw HydrationException::missingDiscriminatorMetaMappingColumn($className, $this->_rsm->discriminatorColumns[$dqlAlias], $dqlAlias); + } + + $discrColumn = $this->_rsm->metaMappings[$this->_rsm->discriminatorColumns[$dqlAlias]]; + + if ( ! isset($data[$discrColumn])) { + throw HydrationException::missingDiscriminatorColumn($className, $discrColumn, $dqlAlias); + } + + if ($data[$discrColumn] === '') { + throw HydrationException::emptyDiscriminatorValue($dqlAlias); + } + + $className = $this->ce[$className]->discriminatorMap[$data[$discrColumn]]; + + unset($data[$discrColumn]); + } + + if (isset($this->_hints[Query::HINT_REFRESH_ENTITY]) && isset($this->rootAliases[$dqlAlias])) { + $this->registerManaged($this->ce[$className], $this->_hints[Query::HINT_REFRESH_ENTITY], $data); + } + + $refresh = $refreshEntity = null; + + if (isset($this->_hints[Query::HINT_REFRESH_ENTITY])) { + $refreshEntity = $this->_hints[Query::HINT_REFRESH_ENTITY]; + } + + if (isset($this->_hints[Query::HINT_REFRESH])) { + $refresh = $this->_hints[Query::HINT_REFRESH]; + } + + unset($this->_hints[Query::HINT_REFRESH_ENTITY], $this->_hints[Query::HINT_REFRESH]); + + $this->_hints['fetchAlias'] = $dqlAlias; + + $entity = $this->_uow->createEntity($className, $data, $this->_hints); + + if (isset($refreshEntity)) { + $this->_hints[Query::HINT_REFRESH_ENTITY] = $refreshEntity; + } + + if (isset($refresh)) { + $this->_hints[Query::HINT_REFRESH] = $refresh; + } + + return $entity; + } + /** * @param string $className * @param array $data @@ -440,7 +505,7 @@ class ObjectHydrator extends AbstractHydrator unset($this->resultPointers[$dqlAlias]); } } else { - $element = $this->getEntity($data, $dqlAlias); + $element = $this->getAssociatedEntity($data, $dqlAlias); if (isset($this->_rsm->indexByMap[$dqlAlias])) { $indexValue = $row[$this->_rsm->indexByMap[$dqlAlias]]; @@ -471,7 +536,7 @@ class ObjectHydrator extends AbstractHydrator // we only need to take action if this value is null, // we refresh the entity or its an unitialized proxy. if (isset($nonemptyComponents[$dqlAlias])) { - $element = $this->getEntity($data, $dqlAlias); + $element = $this->getAssociatedEntity($data, $dqlAlias); $reflField->setValue($parentObject, $element); $this->_uow->setOriginalEntityProperty($oid, $relationField, $element); $targetClass = $this->ce[$relation['targetEntity']]; From c204e6c6a1fdac713190b7d15de562fa493b8946 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Fri, 24 Jan 2014 02:52:30 +0100 Subject: [PATCH 5/8] DDC-2931 - removing old comments --- .../Tests/ORM/Functional/Ticket/DDC2931Test.php | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2931Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2931Test.php index c1b5c613b..560f3ea64 100755 --- a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2931Test.php +++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2931Test.php @@ -38,16 +38,6 @@ class DDC2931Test extends \Doctrine\Tests\OrmFunctionalTestCase $this->_em->flush(); $this->_em->clear(); - // After some debugging, I found that the issue came from - // [`UnitOfWork#createEntity`](https://github.com/doctrine/doctrine2/blob/bba5ec27fbbe35224be48878a0c92827ef2f9733/lib/Doctrine/ORM/UnitOfWork.php#L2512-L2528) with #406 (DCOM-96). - // When initializing the proxy for `$first` (during the `DDC2931User#getRank()` call), the ORM attempts to fetch also `$second` again - // via [`ObjectHydrator#getEntity`](https://github.com/doctrine/doctrine2/blob/bba5ec27fbbe35224be48878a0c92827ef2f9733/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php#L280)`, - // but the hint `doctrine.refresh.entity` contains the initialized proxy, while the identifier passed down - // is the identifier of `$second` (not a proxy). - // `UnitOfWork#createQuery` does some comparisons and detects that in fact, the two objects don't correspond, - // and therefore marks the entity as "to be detached" - - // Load Entity in second order $second = $this->_em->find('Doctrine\Tests\ORM\Functional\Ticket\DDC2931User', $second->id); $this->assertSame(2, $second->getRank()); @@ -75,8 +65,6 @@ class DDC2931User */ public function getRank() { - //$id = $this->parent->id; - //$hash = spl_object_hash($this); return 1 + ($this->parent ? $this->parent->getRank() : 0); } From b596bbb29fb671e82514c6dd05b39a4042c0b237 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sat, 1 Feb 2014 01:05:34 +0100 Subject: [PATCH 6/8] DDC-2931 - adding test that verifies that fetch-joined entities get refreshed with hints --- .../ORM/Functional/Ticket/DDC2931Test.php | 48 ++++++++++++++++++- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2931Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2931Test.php index 560f3ea64..90258b75b 100755 --- a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2931Test.php +++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2931Test.php @@ -2,6 +2,8 @@ namespace Doctrine\Tests\ORM\Functional\Ticket; +use Doctrine\ORM\Query; + require_once __DIR__ . '/../../../TestInit.php'; /** @@ -24,9 +26,9 @@ class DDC2931Test extends \Doctrine\Tests\OrmFunctionalTestCase public function testIssue() { - $first = new DDC2931User(); + $first = new DDC2931User(); $second = new DDC2931User(); - $third = new DDC2931User(); + $third = new DDC2931User(); $second->parent = $first; $third->parent = $second; @@ -42,6 +44,45 @@ class DDC2931Test extends \Doctrine\Tests\OrmFunctionalTestCase $this->assertSame(2, $second->getRank()); } + + public function testFetchJoinedEntitiesCanBeRefreshed() + { + $first = new DDC2931User(); + $second = new DDC2931User(); + $third = new DDC2931User(); + + $second->parent = $first; + $third->parent = $second; + + $first->value = 1; + $second->value = 2; + $third->value = 3; + + $this->_em->persist($first); + $this->_em->persist($second); + $this->_em->persist($third); + + $this->_em->flush(); + + $first->value = 4; + $second->value = 5; + $third->value = 6; + + $refreshedSecond = $this + ->_em + ->createQuery( + 'SELECT e, p, c FROM ' + . __NAMESPACE__ . '\\DDC2931User e LEFT JOIN e.parent p LEFT JOIN e.child c WHERE e = :id' + ) + ->setParameter('id', $second) + ->setHint(Query::HINT_REFRESH, true) + ->getResult(); + + $this->assertCount(1, $refreshedSecond); + $this->assertSame(1, $first->value); + $this->assertSame(2, $second->value); + $this->assertSame(3, $third->value); + } } @@ -58,6 +99,9 @@ class DDC2931User /** @OneToOne(targetEntity="DDC2931User", mappedBy="parent") */ public $child; + /** @Column(type="integer") */ + public $value = 0; + /** * Return Rank recursively * My rank is 1 + rank of my parent From b3ccd6466b4a4a0518a7ffe4d6419df9c949ce40 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sat, 1 Feb 2014 01:57:51 +0100 Subject: [PATCH 7/8] DDC-2931 - Safe comparison between proxies and entities when refreshing objects --- lib/Doctrine/ORM/UnitOfWork.php | 39 ++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/lib/Doctrine/ORM/UnitOfWork.php b/lib/Doctrine/ORM/UnitOfWork.php index e982d6b8b..745b0322e 100644 --- a/lib/Doctrine/ORM/UnitOfWork.php +++ b/lib/Doctrine/ORM/UnitOfWork.php @@ -2498,14 +2498,14 @@ class UnitOfWork implements PropertyChangedListener && isset($hints[Query::HINT_REFRESH_ENTITY]) && ($unmanagedProxy = $hints[Query::HINT_REFRESH_ENTITY]) !== $entity && $unmanagedProxy instanceof Proxy - && (($unmanagedProxyClass = $this->em->getClassMetadata(get_class($unmanagedProxy))) === $class) + && $this->isIdentifierEquals($unmanagedProxy, $entity) ) { // DDC-1238 - we have a managed instance, but it isn't the provided one. // Therefore we clear its identifier. Also, we must re-fetch metadata since the // refreshed object may be anything - foreach ($unmanagedProxyClass->identifier as $fieldName) { - $unmanagedProxyClass->reflFields[$fieldName]->setValue($unmanagedProxy, null); + foreach ($class->identifier as $fieldName) { + $class->reflFields[$fieldName]->setValue($unmanagedProxy, null); } return $unmanagedProxy; @@ -3214,4 +3214,37 @@ class UnitOfWork implements PropertyChangedListener $this->evm->dispatchEvent(Events::postFlush, new PostFlushEventArgs($this->em)); } } + + /** + * Verifies if two given entities actually are the same based on identifier comparison + * + * @param object $entity1 + * @param object $entity2 + * + * @return bool + */ + private function isIdentifierEquals($entity1, $entity2) + { + if ($entity1 === $entity2) { + return true; + } + + $class = $this->em->getClassMetadata(get_class($entity1)); + + if ($class !== $this->em->getClassMetadata(get_class($entity2))) { + return false; + } + + $oid1 = spl_object_hash($entity1); + $oid2 = spl_object_hash($entity2); + + $id1 = isset($this->entityIdentifiers[$oid1]) + ? $this->entityIdentifiers[$oid1] + : $this->flattenIdentifier($class, $class->getIdentifierValues($entity1)); + $id2 = isset($this->entityIdentifiers[$oid2]) + ? $this->entityIdentifiers[$oid2] + : $this->flattenIdentifier($class, $class->getIdentifierValues($entity2)); + + return $id1 === $id2 || implode(' ', $id1) === implode(' ', $id2); + } } From 215c4a03e1a799291705c9298bfbe09938e1ddb3 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sat, 1 Feb 2014 02:00:10 +0100 Subject: [PATCH 8/8] DDC-2931 - Removing previous broken fix for DDC-2931 - hardened --- .../ORM/Internal/Hydration/ObjectHydrator.php | 69 +------------------ 1 file changed, 2 insertions(+), 67 deletions(-) diff --git a/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php b/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php index 27e256814..fafc497c0 100644 --- a/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php +++ b/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php @@ -280,71 +280,6 @@ class ObjectHydrator extends AbstractHydrator return $this->_uow->createEntity($className, $data, $this->_hints); } - /** - * Gets an association entity instance. - * - * @param array $data - * @param string $dqlAlias - * - * @return object The associated entity. - * - * @throws HydrationException - */ - private function getAssociatedEntity(array $data, $dqlAlias) - { - $className = $this->_rsm->aliasMap[$dqlAlias]; - - if (isset($this->_rsm->discriminatorColumns[$dqlAlias])) { - if ( ! isset($this->_rsm->metaMappings[$this->_rsm->discriminatorColumns[$dqlAlias]])) { - throw HydrationException::missingDiscriminatorMetaMappingColumn($className, $this->_rsm->discriminatorColumns[$dqlAlias], $dqlAlias); - } - - $discrColumn = $this->_rsm->metaMappings[$this->_rsm->discriminatorColumns[$dqlAlias]]; - - if ( ! isset($data[$discrColumn])) { - throw HydrationException::missingDiscriminatorColumn($className, $discrColumn, $dqlAlias); - } - - if ($data[$discrColumn] === '') { - throw HydrationException::emptyDiscriminatorValue($dqlAlias); - } - - $className = $this->ce[$className]->discriminatorMap[$data[$discrColumn]]; - - unset($data[$discrColumn]); - } - - if (isset($this->_hints[Query::HINT_REFRESH_ENTITY]) && isset($this->rootAliases[$dqlAlias])) { - $this->registerManaged($this->ce[$className], $this->_hints[Query::HINT_REFRESH_ENTITY], $data); - } - - $refresh = $refreshEntity = null; - - if (isset($this->_hints[Query::HINT_REFRESH_ENTITY])) { - $refreshEntity = $this->_hints[Query::HINT_REFRESH_ENTITY]; - } - - if (isset($this->_hints[Query::HINT_REFRESH])) { - $refresh = $this->_hints[Query::HINT_REFRESH]; - } - - unset($this->_hints[Query::HINT_REFRESH_ENTITY], $this->_hints[Query::HINT_REFRESH]); - - $this->_hints['fetchAlias'] = $dqlAlias; - - $entity = $this->_uow->createEntity($className, $data, $this->_hints); - - if (isset($refreshEntity)) { - $this->_hints[Query::HINT_REFRESH_ENTITY] = $refreshEntity; - } - - if (isset($refresh)) { - $this->_hints[Query::HINT_REFRESH] = $refresh; - } - - return $entity; - } - /** * @param string $className * @param array $data @@ -505,7 +440,7 @@ class ObjectHydrator extends AbstractHydrator unset($this->resultPointers[$dqlAlias]); } } else { - $element = $this->getAssociatedEntity($data, $dqlAlias); + $element = $this->getEntity($data, $dqlAlias); if (isset($this->_rsm->indexByMap[$dqlAlias])) { $indexValue = $row[$this->_rsm->indexByMap[$dqlAlias]]; @@ -536,7 +471,7 @@ class ObjectHydrator extends AbstractHydrator // we only need to take action if this value is null, // we refresh the entity or its an unitialized proxy. if (isset($nonemptyComponents[$dqlAlias])) { - $element = $this->getAssociatedEntity($data, $dqlAlias); + $element = $this->getEntity($data, $dqlAlias); $reflField->setValue($parentObject, $element); $this->_uow->setOriginalEntityProperty($oid, $relationField, $element); $targetClass = $this->ce[$relation['targetEntity']];