DDC-952 - Implemented first approach for batching eager loads of ToOne associations.
This commit is contained in:
parent
e0b835178b
commit
32df9451fd
@ -59,6 +59,7 @@ class ObjectHydrator extends AbstractHydrator
|
||||
$this->_resultPointers =
|
||||
$this->_idTemplate = array();
|
||||
$this->_resultCounter = 0;
|
||||
$this->_hints['deferEagerLoad'] = true;
|
||||
|
||||
foreach ($this->_rsm->aliasMap as $dqlAlias => $className) {
|
||||
$this->_identifierMap[$dqlAlias] = array();
|
||||
@ -132,6 +133,8 @@ class ObjectHydrator extends AbstractHydrator
|
||||
$coll->takeSnapshot();
|
||||
}
|
||||
|
||||
$this->_em->getUnitOfWork()->triggerEagerLoads();
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
@ -560,7 +560,10 @@ class BasicEntityPersister
|
||||
$result = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
$stmt->closeCursor();
|
||||
|
||||
return $this->_createEntity($result, $entity, $hints);
|
||||
$hints['deferEagerLoad'] = true;
|
||||
$entity = $this->_createEntity($result, $entity, $hints);
|
||||
$this->_em->getUnitOfWork()->triggerEagerLoads();
|
||||
return $entity;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -577,6 +580,10 @@ class BasicEntityPersister
|
||||
*/
|
||||
public function loadOneToOneEntity(array $assoc, $sourceEntity, $targetEntity, array $identifier = array())
|
||||
{
|
||||
if ($foundEntity = $this->_em->getUnitOfWork()->tryGetById($identifier, $assoc['targetEntity'])) {
|
||||
return $foundEntity;
|
||||
}
|
||||
|
||||
$targetClass = $this->_em->getClassMetadata($assoc['targetEntity']);
|
||||
|
||||
if ($assoc['isOwningSide']) {
|
||||
@ -739,10 +746,13 @@ class BasicEntityPersister
|
||||
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
$stmt->closeCursor();
|
||||
|
||||
$hints = array('deferEagerLoads' => true);
|
||||
foreach ($result as $row) {
|
||||
$entities[] = $this->_createEntity($row);
|
||||
$entities[] = $this->_createEntity($row, null, $hints);
|
||||
}
|
||||
|
||||
$this->_em->getUnitOfWork()->triggerEagerLoads();
|
||||
|
||||
return $entities;
|
||||
}
|
||||
|
||||
@ -870,7 +880,14 @@ class BasicEntityPersister
|
||||
|
||||
$sql = $this->_getSelectEntitiesSQL($criteria, $assoc, 0, $limit, $offset);
|
||||
list($params, $types) = $this->expandParameters($criteria);
|
||||
return $this->_conn->executeQuery($sql, $params, $types);
|
||||
$stmt = $this->_conn->executeQuery($sql, $params, $types);
|
||||
$hints = array('deferEagerLoads' => true);
|
||||
while ($result = $stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||
$coll->hydrateAdd($this->_createEntity($result, null, $hints));
|
||||
}
|
||||
$stmt->closeCursor();
|
||||
|
||||
$this->_em->getUnitOfWork()->triggerEagerLoads();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1330,7 +1347,16 @@ class BasicEntityPersister
|
||||
|
||||
$sql = $this->_getSelectEntitiesSQL($criteria, $assoc, 0, $limit, $offset);
|
||||
list($params, $types) = $this->expandParameters($criteria);
|
||||
return $this->_conn->executeQuery($sql, $params, $types);
|
||||
|
||||
$stmt = $this->_conn->executeQuery($sql, $params, $types);
|
||||
$hints = array('deferEagerLoads' => true);
|
||||
while ($result = $stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||
$coll->hydrateAdd($this->_createEntity($result, null, $hints));
|
||||
}
|
||||
$stmt->closeCursor();
|
||||
|
||||
$this->_em->getUnitOfWork()->triggerEagerLoads();
|
||||
return $stmt;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1928,10 +1928,18 @@ class UnitOfWork implements PropertyChangedListener
|
||||
$newValue = $this->getEntityPersister($assoc['targetEntity'])
|
||||
->loadOneToOneEntity($assoc, $entity, null, $associatedId);
|
||||
} else {
|
||||
if ($assoc['fetch'] == ClassMetadata::FETCH_EAGER) {
|
||||
// TODO: Maybe it could be optimized to do an eager fetch with a JOIN inside
|
||||
// the persister instead of this rather unperformant approach.
|
||||
$newValue = $this->em->find($assoc['targetEntity'], $associatedId);
|
||||
if ($assoc['fetch'] == ClassMetadata::FETCH_EAGER && isset($hints['deferEagerLoad'])) {
|
||||
if (!isset($this->eagerLoadingEntities[$assoc['targetEntity']])) {
|
||||
$this->eagerLoadingEntities[$assoc['targetEntity']] = array();
|
||||
}
|
||||
|
||||
// TODO: Is there a faster approach?
|
||||
$this->eagerLoadingEntities[$assoc['targetEntity']] = array_merge_recursive(
|
||||
$this->eagerLoadingEntities[$assoc['targetEntity']],
|
||||
array_map(function($id) {
|
||||
return array($id);
|
||||
}, $associatedId)
|
||||
);
|
||||
} else {
|
||||
$newValue = $this->em->getProxyFactory()->getProxy($assoc['targetEntity'], $associatedId);
|
||||
}
|
||||
@ -1983,6 +1991,26 @@ class UnitOfWork implements PropertyChangedListener
|
||||
}
|
||||
|
||||
/**
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
* @return void
|
||||
*/
|
||||
public function triggerEagerLoads()
|
||||
{
|
||||
if (!$this->eagerLoadingEntities) {
|
||||
return;
|
||||
}
|
||||
|
||||
$eagerLoadingEntities = $this->eagerLoadingEntities;
|
||||
$this->eagerLoadingEntities = array();
|
||||
|
||||
foreach ($eagerLoadingEntities AS $entityName => $ids) {
|
||||
$this->getEntityPersister($entityName)->loadAll($ids);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
>>>>>>> DDC-952 - Implemented first approach for batching eager loads of ToOne associations.
|
||||
* Initializes (loads) an uninitialized persistent collection of an entity.
|
||||
*
|
||||
* @param PeristentCollection $collection The collection to initialize.
|
||||
|
@ -21,6 +21,10 @@ class DDC633Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-633
|
||||
* @group DDC-952
|
||||
*/
|
||||
public function testOneToOneEager()
|
||||
{
|
||||
$app = new DDC633Appointment();
|
||||
@ -35,7 +39,35 @@ class DDC633Test extends \Doctrine\Tests\OrmFunctionalTestCase
|
||||
|
||||
$eagerAppointment = $this->_em->find(__NAMESPACE__ . '\DDC633Appointment', $app->id);
|
||||
|
||||
$this->assertNotType('Doctrine\ORM\Proxy\Proxy', $eagerAppointment->patient);
|
||||
// Eager loading still produces proxies
|
||||
$this->assertType('Doctrine\ORM\Proxy\Proxy', $eagerAppointment->patient);
|
||||
$this->assertTrue($eagerAppointment->patient->__isInitialized__, "Proxy should already be initialized due to eager loading!");
|
||||
}
|
||||
|
||||
/**
|
||||
* @group DDC-633
|
||||
* @group DDC-952
|
||||
*/
|
||||
public function testDQLDeferredEagerLoad()
|
||||
{
|
||||
for ($i = 0; $i < 10; $i++) {
|
||||
$app = new DDC633Appointment();
|
||||
$pat = new DDC633Patient();
|
||||
$app->patient = $pat;
|
||||
$pat->appointment = $app;
|
||||
|
||||
$this->_em->persist($app);
|
||||
$this->_em->persist($pat);
|
||||
}
|
||||
$this->_em->flush();
|
||||
$this->_em->clear();
|
||||
|
||||
$appointments = $this->_em->createQuery("SELECT a FROM " . __NAMESPACE__ . "\DDC633Appointment a")->getResult();
|
||||
|
||||
foreach ($appointments AS $eagerAppointment) {
|
||||
$this->assertType('Doctrine\ORM\Proxy\Proxy', $eagerAppointment->patient);
|
||||
$this->assertTrue($eagerAppointment->patient->__isInitialized__, "Proxy should already be initialized due to eager loading!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user