Fix cache misses using one-to-one inverse side
This commit is contained in:
parent
8554b04053
commit
cf4c805427
@ -21,7 +21,6 @@
|
|||||||
namespace Doctrine\ORM\Cache;
|
namespace Doctrine\ORM\Cache;
|
||||||
|
|
||||||
use Doctrine\ORM\Query;
|
use Doctrine\ORM\Query;
|
||||||
use Doctrine\Common\Proxy\Proxy;
|
|
||||||
use Doctrine\ORM\Cache\EntityCacheKey;
|
use Doctrine\ORM\Cache\EntityCacheKey;
|
||||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
@ -133,7 +132,7 @@ class DefaultEntityHydrator implements EntityHydrator
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$data[$name] = $assoc['fetch'] === ClassMetadata::FETCH_EAGER
|
$data[$name] = $assoc['fetch'] === ClassMetadata::FETCH_EAGER || ($assoc['type'] === ClassMetadata::ONE_TO_ONE && ! $assoc['isOwningSide'])
|
||||||
? $this->uow->createEntity($assocEntry->class, $assocEntry->data, $hints)
|
? $this->uow->createEntity($assocEntry->class, $assocEntry->data, $hints)
|
||||||
: $this->em->getReference($assocEntry->class, $assocId);
|
: $this->em->getReference($assocEntry->class, $assocId);
|
||||||
}
|
}
|
||||||
|
@ -100,6 +100,13 @@ abstract class AbstractEntityPersister implements CachedEntityPersister
|
|||||||
*/
|
*/
|
||||||
protected $regionName;
|
protected $regionName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Associations configured as FETCH_EAGER, as well as all inverse one-to-one associations.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $joinedAssociations;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param \Doctrine\ORM\Persisters\EntityPersister $persister The entity persister to cache.
|
* @param \Doctrine\ORM\Persisters\EntityPersister $persister The entity persister to cache.
|
||||||
* @param \Doctrine\ORM\Cache\Region $region The entity cache region.
|
* @param \Doctrine\ORM\Cache\Region $region The entity cache region.
|
||||||
@ -227,6 +234,42 @@ abstract class AbstractEntityPersister implements CachedEntityPersister
|
|||||||
return $cached;
|
return $cached;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param object $entity
|
||||||
|
*/
|
||||||
|
private function storeJoinedAssociations($entity)
|
||||||
|
{
|
||||||
|
if ($this->joinedAssociations === null) {
|
||||||
|
$associations = array();
|
||||||
|
|
||||||
|
foreach ($this->class->associationMappings as $name => $assoc) {
|
||||||
|
if (isset($assoc['cache']) &&
|
||||||
|
($assoc['type'] & ClassMetadata::TO_ONE) &&
|
||||||
|
($assoc['fetch'] === ClassMetadata::FETCH_EAGER || ! $assoc['isOwningSide'])) {
|
||||||
|
|
||||||
|
$associations[] = $name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->joinedAssociations = $associations;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($this->joinedAssociations as $name) {
|
||||||
|
$assoc = $this->class->associationMappings[$name];
|
||||||
|
$assocEntity = $this->class->getFieldValue($entity, $name);
|
||||||
|
|
||||||
|
if ($assocEntity === null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$assocId = $this->uow->getEntityIdentifier($assocEntity);
|
||||||
|
$assocKey = new EntityCacheKey($assoc['targetEntity'], $assocId);
|
||||||
|
$assocPersister = $this->uow->getEntityPersister($assoc['targetEntity']);
|
||||||
|
|
||||||
|
$assocPersister->storeEntityCache($assocEntity, $assocKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a string of currently query
|
* Generates a string of currently query
|
||||||
*
|
*
|
||||||
@ -417,6 +460,10 @@ abstract class AbstractEntityPersister implements CachedEntityPersister
|
|||||||
$cacheEntry = $this->hydrator->buildCacheEntry($class, $cacheKey, $entity);
|
$cacheEntry = $this->hydrator->buildCacheEntry($class, $cacheKey, $entity);
|
||||||
$cached = $this->region->put($cacheKey, $cacheEntry);
|
$cached = $this->region->put($cacheKey, $cacheEntry);
|
||||||
|
|
||||||
|
if ($cached && ($this->joinedAssociations === null || count($this->joinedAssociations) > 0)) {
|
||||||
|
$this->storeJoinedAssociations($entity);
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->cacheLogger) {
|
if ($this->cacheLogger) {
|
||||||
if ($cached) {
|
if ($cached) {
|
||||||
$this->cacheLogger->entityCachePut($this->regionName, $cacheKey);
|
$this->cacheLogger->entityCachePut($this->regionName, $cacheKey);
|
||||||
|
@ -2602,6 +2602,18 @@ class UnitOfWork implements PropertyChangedListener
|
|||||||
switch (true) {
|
switch (true) {
|
||||||
case ($assoc['type'] & ClassMetadata::TO_ONE):
|
case ($assoc['type'] & ClassMetadata::TO_ONE):
|
||||||
if ( ! $assoc['isOwningSide']) {
|
if ( ! $assoc['isOwningSide']) {
|
||||||
|
|
||||||
|
// use the given entity association
|
||||||
|
if (isset($data[$field]) && is_object($data[$field]) && isset($this->entityStates[spl_object_hash($data[$field])])) {
|
||||||
|
|
||||||
|
$this->originalEntityData[$oid][$field] = $data[$field];
|
||||||
|
|
||||||
|
$class->reflFields[$field]->setValue($entity, $data[$field]);
|
||||||
|
$targetClass->reflFields[$assoc['mappedBy']]->setValue($data[$field], $entity);
|
||||||
|
|
||||||
|
continue 2;
|
||||||
|
}
|
||||||
|
|
||||||
// Inverse side of x-to-one can never be lazy
|
// Inverse side of x-to-one can never be lazy
|
||||||
$class->reflFields[$field]->setValue($entity, $this->getEntityPersister($assoc['targetEntity'])->loadOneToOneEntity($assoc, $entity));
|
$class->reflFields[$field]->setValue($entity, $this->getEntityPersister($assoc['targetEntity'])->loadOneToOneEntity($assoc, $entity));
|
||||||
|
|
||||||
|
@ -7,5 +7,5 @@ namespace Doctrine\Tests\Models\Cache;
|
|||||||
*/
|
*/
|
||||||
class Beach extends Attraction
|
class Beach extends Attraction
|
||||||
{
|
{
|
||||||
const CLASSNAME = __CLASS__;
|
const CLASSNAME = __CLASS__;
|
||||||
}
|
}
|
@ -33,6 +33,12 @@ class Traveler
|
|||||||
*/
|
*/
|
||||||
public $travels;
|
public $travels;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Cache
|
||||||
|
* @OneToOne(targetEntity="TravelerProfile")
|
||||||
|
*/
|
||||||
|
protected $profile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $name
|
* @param string $name
|
||||||
*/
|
*/
|
||||||
@ -62,6 +68,22 @@ class Traveler
|
|||||||
$this->name = $name;
|
$this->name = $name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \Doctrine\Tests\Models\Cache\TravelerProfile
|
||||||
|
*/
|
||||||
|
public function getProfile()
|
||||||
|
{
|
||||||
|
return $this->profile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \Doctrine\Tests\Models\Cache\TravelerProfile $profile
|
||||||
|
*/
|
||||||
|
public function setProfile(TravelerProfile $profile)
|
||||||
|
{
|
||||||
|
$this->profile = $profile;
|
||||||
|
}
|
||||||
|
|
||||||
public function getTravels()
|
public function getTravels()
|
||||||
{
|
{
|
||||||
return $this->travels;
|
return $this->travels;
|
||||||
@ -88,4 +110,4 @@ class Traveler
|
|||||||
{
|
{
|
||||||
$this->travels->removeElement($item);
|
$this->travels->removeElement($item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
66
tests/Doctrine/Tests/Models/Cache/TravelerProfile.php
Normal file
66
tests/Doctrine/Tests/Models/Cache/TravelerProfile.php
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Doctrine\Tests\Models\Cache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Entity
|
||||||
|
* @Table("cache_traveler_profile")
|
||||||
|
* @Cache("NONSTRICT_READ_WRITE")
|
||||||
|
*/
|
||||||
|
class TravelerProfile
|
||||||
|
{
|
||||||
|
const CLASSNAME = __CLASS__;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Id
|
||||||
|
* @GeneratedValue
|
||||||
|
* @Column(type="integer")
|
||||||
|
*/
|
||||||
|
protected $id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Column(unique=true)
|
||||||
|
*/
|
||||||
|
private $name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @OneToOne(targetEntity="TravelerProfileInfo", mappedBy="profile")
|
||||||
|
* @Cache()
|
||||||
|
*/
|
||||||
|
private $info;
|
||||||
|
|
||||||
|
public function __construct($name)
|
||||||
|
{
|
||||||
|
$this->name = $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getId()
|
||||||
|
{
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setId($id)
|
||||||
|
{
|
||||||
|
$this->id = $id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getName()
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setName($nae)
|
||||||
|
{
|
||||||
|
$this->name = $nae;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getInfo()
|
||||||
|
{
|
||||||
|
return $this->info;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setInfo(TravelerProfileInfo $info)
|
||||||
|
{
|
||||||
|
$this->info = $info;
|
||||||
|
}
|
||||||
|
}
|
68
tests/Doctrine/Tests/Models/Cache/TravelerProfileInfo.php
Normal file
68
tests/Doctrine/Tests/Models/Cache/TravelerProfileInfo.php
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Doctrine\Tests\Models\Cache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Entity
|
||||||
|
* @Table("cache_traveler_profile_info")
|
||||||
|
* @Cache("NONSTRICT_READ_WRITE")
|
||||||
|
*/
|
||||||
|
class TravelerProfileInfo
|
||||||
|
{
|
||||||
|
const CLASSNAME = __CLASS__;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Id
|
||||||
|
* @GeneratedValue
|
||||||
|
* @Column(type="integer")
|
||||||
|
*/
|
||||||
|
protected $id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Column(unique=true)
|
||||||
|
*/
|
||||||
|
private $description;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Cache()
|
||||||
|
* @JoinColumn(name="profile_id", referencedColumnName="id")
|
||||||
|
* @OneToOne(targetEntity="TravelerProfile", inversedBy="info")
|
||||||
|
*/
|
||||||
|
private $profile;
|
||||||
|
|
||||||
|
public function __construct(TravelerProfile $profile, $description)
|
||||||
|
{
|
||||||
|
$this->profile = $profile;
|
||||||
|
$this->description = $description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getId()
|
||||||
|
{
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setId($id)
|
||||||
|
{
|
||||||
|
$this->id = $id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDescription()
|
||||||
|
{
|
||||||
|
return $this->description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setDescription($description)
|
||||||
|
{
|
||||||
|
$this->description = $description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getProfile()
|
||||||
|
{
|
||||||
|
return $this->profile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setProfile(TravelerProfile $profile)
|
||||||
|
{
|
||||||
|
$this->profile = $profile;
|
||||||
|
}
|
||||||
|
}
|
@ -26,6 +26,9 @@ class OneToOneEagerLoadingTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||||||
} catch(\Exception $e) {}
|
} catch(\Exception $e) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group non-cacheable
|
||||||
|
*/
|
||||||
public function testEagerLoadOneToOneOwningSide()
|
public function testEagerLoadOneToOneOwningSide()
|
||||||
{
|
{
|
||||||
$train = new Train(new TrainOwner("Alexander"));
|
$train = new Train(new TrainOwner("Alexander"));
|
||||||
@ -48,6 +51,9 @@ class OneToOneEagerLoadingTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||||||
$this->assertEquals($sqlCount + 1, count($this->_sqlLoggerStack->queries));
|
$this->assertEquals($sqlCount + 1, count($this->_sqlLoggerStack->queries));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group non-cacheable
|
||||||
|
*/
|
||||||
public function testEagerLoadOneToOneNullOwningSide()
|
public function testEagerLoadOneToOneNullOwningSide()
|
||||||
{
|
{
|
||||||
$train = new Train(new TrainOwner("Alexander"));
|
$train = new Train(new TrainOwner("Alexander"));
|
||||||
@ -65,6 +71,9 @@ class OneToOneEagerLoadingTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||||||
$this->assertEquals($sqlCount + 1, count($this->_sqlLoggerStack->queries));
|
$this->assertEquals($sqlCount + 1, count($this->_sqlLoggerStack->queries));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group non-cacheable
|
||||||
|
*/
|
||||||
public function testEagerLoadOneToOneInverseSide()
|
public function testEagerLoadOneToOneInverseSide()
|
||||||
{
|
{
|
||||||
$owner = new TrainOwner("Alexander");
|
$owner = new TrainOwner("Alexander");
|
||||||
@ -83,6 +92,9 @@ class OneToOneEagerLoadingTest extends \Doctrine\Tests\OrmFunctionalTestCase
|
|||||||
$this->assertEquals($sqlCount + 1, count($this->_sqlLoggerStack->queries));
|
$this->assertEquals($sqlCount + 1, count($this->_sqlLoggerStack->queries));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group non-cacheable
|
||||||
|
*/
|
||||||
public function testEagerLoadOneToOneNullInverseSide()
|
public function testEagerLoadOneToOneNullInverseSide()
|
||||||
{
|
{
|
||||||
$driver = new TrainDriver("Dagny Taggert");
|
$driver = new TrainDriver("Dagny Taggert");
|
||||||
|
@ -8,6 +8,8 @@ use Doctrine\Tests\Models\Cache\Country;
|
|||||||
use Doctrine\Tests\Models\Cache\State;
|
use Doctrine\Tests\Models\Cache\State;
|
||||||
use Doctrine\Tests\Models\Cache\City;
|
use Doctrine\Tests\Models\Cache\City;
|
||||||
|
|
||||||
|
use Doctrine\Tests\Models\Cache\TravelerProfileInfo;
|
||||||
|
use Doctrine\Tests\Models\Cache\TravelerProfile;
|
||||||
use Doctrine\Tests\Models\Cache\Traveler;
|
use Doctrine\Tests\Models\Cache\Traveler;
|
||||||
use Doctrine\Tests\Models\Cache\Travel;
|
use Doctrine\Tests\Models\Cache\Travel;
|
||||||
|
|
||||||
@ -23,13 +25,14 @@ use Doctrine\Tests\Models\Cache\AttractionLocationInfo;
|
|||||||
*/
|
*/
|
||||||
abstract class SecondLevelCacheAbstractTest extends OrmFunctionalTestCase
|
abstract class SecondLevelCacheAbstractTest extends OrmFunctionalTestCase
|
||||||
{
|
{
|
||||||
protected $countries = array();
|
protected $countries = array();
|
||||||
protected $states = array();
|
protected $states = array();
|
||||||
protected $cities = array();
|
protected $cities = array();
|
||||||
protected $travels = array();
|
protected $travels = array();
|
||||||
protected $travelers = array();
|
protected $travelers = array();
|
||||||
protected $attractions = array();
|
protected $attractions = array();
|
||||||
protected $attractionsInfo = array();
|
protected $attractionsInfo = array();
|
||||||
|
protected $travelersWithProfile = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var \Doctrine\ORM\Cache
|
* @var \Doctrine\ORM\Cache
|
||||||
@ -118,6 +121,45 @@ abstract class SecondLevelCacheAbstractTest extends OrmFunctionalTestCase
|
|||||||
|
|
||||||
$this->_em->flush();
|
$this->_em->flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function loadFixturesTravelersWithProfile()
|
||||||
|
{
|
||||||
|
$t1 = new Traveler("Test traveler 1");
|
||||||
|
$t2 = new Traveler("Test traveler 2");
|
||||||
|
$p1 = new TravelerProfile("First Traveler Profile");
|
||||||
|
$p2 = new TravelerProfile("Second Traveler Profile");
|
||||||
|
|
||||||
|
$t1->setProfile($p1);
|
||||||
|
$t2->setProfile($p2);
|
||||||
|
|
||||||
|
$this->_em->persist($p1);
|
||||||
|
$this->_em->persist($p2);
|
||||||
|
$this->_em->persist($t1);
|
||||||
|
$this->_em->persist($t2);
|
||||||
|
|
||||||
|
$this->travelersWithProfile[] = $t1;
|
||||||
|
$this->travelersWithProfile[] = $t2;
|
||||||
|
|
||||||
|
$this->_em->flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function loadFixturesTravelersProfileInfo()
|
||||||
|
{
|
||||||
|
$p1 = $this->travelersWithProfile[0]->getProfile();
|
||||||
|
$p2 = $this->travelersWithProfile[1]->getProfile();
|
||||||
|
$i1 = new TravelerProfileInfo($p1, "First Profile Info ...");
|
||||||
|
$i2 = new TravelerProfileInfo($p2, "Second Profile Info ...");
|
||||||
|
|
||||||
|
$p1->setInfo($i1);
|
||||||
|
$p2->setInfo($i2);
|
||||||
|
|
||||||
|
$this->_em->persist($i1);
|
||||||
|
$this->_em->persist($i2);
|
||||||
|
$this->_em->persist($p1);
|
||||||
|
$this->_em->persist($p2);
|
||||||
|
|
||||||
|
$this->_em->flush();
|
||||||
|
}
|
||||||
|
|
||||||
protected function loadFixturesTravels()
|
protected function loadFixturesTravels()
|
||||||
{
|
{
|
||||||
|
@ -0,0 +1,190 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Doctrine\Tests\ORM\Functional;
|
||||||
|
|
||||||
|
use Doctrine\Tests\Models\Cache\Traveler;
|
||||||
|
use Doctrine\Tests\Models\Cache\TravelerProfile;
|
||||||
|
use Doctrine\Tests\Models\Cache\TravelerProfileInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group DDC-2183
|
||||||
|
*/
|
||||||
|
class SecondLevelCacheOneToOneTest extends SecondLevelCacheAbstractTest
|
||||||
|
{
|
||||||
|
public function testPutOneToOneOnUnidirectionalPersist()
|
||||||
|
{
|
||||||
|
$this->loadFixturesCountries();
|
||||||
|
$this->loadFixturesStates();
|
||||||
|
$this->loadFixturesCities();
|
||||||
|
$this->loadFixturesTravelersWithProfile();
|
||||||
|
|
||||||
|
$this->_em->clear();
|
||||||
|
|
||||||
|
$entity1 = $this->travelersWithProfile[0];
|
||||||
|
$entity2 = $this->travelersWithProfile[1];
|
||||||
|
|
||||||
|
$this->assertTrue($this->cache->containsEntity(Traveler::CLASSNAME, $entity1->getId()));
|
||||||
|
$this->assertTrue($this->cache->containsEntity(Traveler::CLASSNAME, $entity2->getId()));
|
||||||
|
$this->assertTrue($this->cache->containsEntity(TravelerProfile::CLASSNAME, $entity1->getProfile()->getId()));
|
||||||
|
$this->assertTrue($this->cache->containsEntity(TravelerProfile::CLASSNAME, $entity2->getProfile()->getId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testPutOneToOneOnBidirectionalPersist()
|
||||||
|
{
|
||||||
|
$this->loadFixturesCountries();
|
||||||
|
$this->loadFixturesStates();
|
||||||
|
$this->loadFixturesCities();
|
||||||
|
$this->loadFixturesTravelersWithProfile();
|
||||||
|
$this->loadFixturesTravelersProfileInfo();
|
||||||
|
|
||||||
|
$this->_em->clear();
|
||||||
|
|
||||||
|
$entity1 = $this->travelersWithProfile[0];
|
||||||
|
$entity2 = $this->travelersWithProfile[1];
|
||||||
|
|
||||||
|
$this->assertTrue($this->cache->containsEntity(Traveler::CLASSNAME, $entity1->getId()));
|
||||||
|
$this->assertTrue($this->cache->containsEntity(Traveler::CLASSNAME, $entity2->getId()));
|
||||||
|
$this->assertTrue($this->cache->containsEntity(TravelerProfile::CLASSNAME, $entity1->getProfile()->getId()));
|
||||||
|
$this->assertTrue($this->cache->containsEntity(TravelerProfile::CLASSNAME, $entity2->getProfile()->getId()));
|
||||||
|
$this->assertTrue($this->cache->containsEntity(TravelerProfileInfo::CLASSNAME, $entity1->getProfile()->getInfo()->getId()));
|
||||||
|
$this->assertTrue($this->cache->containsEntity(TravelerProfileInfo::CLASSNAME, $entity2->getProfile()->getInfo()->getId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testPutAndLoadOneToOneUnidirectionalRelation()
|
||||||
|
{
|
||||||
|
$this->loadFixturesCountries();
|
||||||
|
$this->loadFixturesStates();
|
||||||
|
$this->loadFixturesCities();
|
||||||
|
$this->loadFixturesTravelersWithProfile();
|
||||||
|
$this->loadFixturesTravelersProfileInfo();
|
||||||
|
|
||||||
|
$this->_em->clear();
|
||||||
|
|
||||||
|
$this->cache->evictEntityRegion(Traveler::CLASSNAME);
|
||||||
|
$this->cache->evictEntityRegion(TravelerProfile::CLASSNAME);
|
||||||
|
|
||||||
|
$entity1 = $this->travelersWithProfile[0];
|
||||||
|
$entity2 = $this->travelersWithProfile[1];
|
||||||
|
|
||||||
|
$this->assertFalse($this->cache->containsEntity(Traveler::CLASSNAME, $entity1->getId()));
|
||||||
|
$this->assertFalse($this->cache->containsEntity(Traveler::CLASSNAME, $entity2->getId()));
|
||||||
|
$this->assertFalse($this->cache->containsEntity(TravelerProfile::CLASSNAME, $entity1->getProfile()->getId()));
|
||||||
|
$this->assertFalse($this->cache->containsEntity(TravelerProfile::CLASSNAME, $entity2->getProfile()->getId()));
|
||||||
|
|
||||||
|
$t1 = $this->_em->find(Traveler::CLASSNAME, $entity1->getId());
|
||||||
|
$t2 = $this->_em->find(Traveler::CLASSNAME, $entity2->getId());
|
||||||
|
|
||||||
|
$this->assertTrue($this->cache->containsEntity(Traveler::CLASSNAME, $entity1->getId()));
|
||||||
|
$this->assertTrue($this->cache->containsEntity(Traveler::CLASSNAME, $entity2->getId()));
|
||||||
|
// The inverse side its not cached
|
||||||
|
$this->assertFalse($this->cache->containsEntity(TravelerProfile::CLASSNAME, $entity1->getProfile()->getId()));
|
||||||
|
$this->assertFalse($this->cache->containsEntity(TravelerProfile::CLASSNAME, $entity2->getProfile()->getId()));
|
||||||
|
|
||||||
|
$this->assertInstanceOf(Traveler::CLASSNAME, $t1);
|
||||||
|
$this->assertInstanceOf(Traveler::CLASSNAME, $t2);
|
||||||
|
$this->assertInstanceOf(TravelerProfile::CLASSNAME, $t1->getProfile());
|
||||||
|
$this->assertInstanceOf(TravelerProfile::CLASSNAME, $t2->getProfile());
|
||||||
|
|
||||||
|
$this->assertEquals($entity1->getId(), $t1->getId());
|
||||||
|
$this->assertEquals($entity1->getName(), $t1->getName());
|
||||||
|
$this->assertEquals($entity1->getProfile()->getId(), $t1->getProfile()->getId());
|
||||||
|
$this->assertEquals($entity1->getProfile()->getName(), $t1->getProfile()->getName());
|
||||||
|
|
||||||
|
$this->assertEquals($entity2->getId(), $t2->getId());
|
||||||
|
$this->assertEquals($entity2->getName(), $t2->getName());
|
||||||
|
$this->assertEquals($entity2->getProfile()->getId(), $t2->getProfile()->getId());
|
||||||
|
$this->assertEquals($entity2->getProfile()->getName(), $t2->getProfile()->getName());
|
||||||
|
|
||||||
|
// its all cached now
|
||||||
|
$this->assertTrue($this->cache->containsEntity(Traveler::CLASSNAME, $entity1->getId()));
|
||||||
|
$this->assertTrue($this->cache->containsEntity(Traveler::CLASSNAME, $entity2->getId()));
|
||||||
|
$this->assertTrue($this->cache->containsEntity(TravelerProfile::CLASSNAME, $entity1->getProfile()->getId()));
|
||||||
|
$this->assertTrue($this->cache->containsEntity(TravelerProfile::CLASSNAME, $entity1->getProfile()->getId()));
|
||||||
|
|
||||||
|
$this->_em->clear();
|
||||||
|
|
||||||
|
$queryCount = $this->getCurrentQueryCount();
|
||||||
|
// load from cache
|
||||||
|
$t3 = $this->_em->find(Traveler::CLASSNAME, $entity1->getId());
|
||||||
|
$t4 = $this->_em->find(Traveler::CLASSNAME, $entity2->getId());
|
||||||
|
|
||||||
|
$this->assertInstanceOf(Traveler::CLASSNAME, $t3);
|
||||||
|
$this->assertInstanceOf(Traveler::CLASSNAME, $t4);
|
||||||
|
$this->assertInstanceOf(TravelerProfile::CLASSNAME, $t3->getProfile());
|
||||||
|
$this->assertInstanceOf(TravelerProfile::CLASSNAME, $t4->getProfile());
|
||||||
|
|
||||||
|
$this->assertEquals($entity1->getProfile()->getId(), $t3->getProfile()->getId());
|
||||||
|
$this->assertEquals($entity2->getProfile()->getId(), $t4->getProfile()->getId());
|
||||||
|
|
||||||
|
$this->assertEquals($entity1->getProfile()->getName(), $t3->getProfile()->getName());
|
||||||
|
$this->assertEquals($entity2->getProfile()->getName(), $t4->getProfile()->getName());
|
||||||
|
|
||||||
|
$this->assertEquals($queryCount, $this->getCurrentQueryCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testPutAndLoadOneToOneBidirectionalRelation()
|
||||||
|
{
|
||||||
|
$this->loadFixturesCountries();
|
||||||
|
$this->loadFixturesStates();
|
||||||
|
$this->loadFixturesCities();
|
||||||
|
$this->loadFixturesTravelersWithProfile();
|
||||||
|
$this->loadFixturesTravelersProfileInfo();
|
||||||
|
|
||||||
|
$this->_em->clear();
|
||||||
|
|
||||||
|
$this->cache->evictEntityRegion(Traveler::CLASSNAME);
|
||||||
|
$this->cache->evictEntityRegion(TravelerProfile::CLASSNAME);
|
||||||
|
$this->cache->evictEntityRegion(TravelerProfileInfo::CLASSNAME);
|
||||||
|
|
||||||
|
$entity1 = $this->travelersWithProfile[0]->getProfile();
|
||||||
|
$entity2 = $this->travelersWithProfile[1]->getProfile();
|
||||||
|
|
||||||
|
$this->assertFalse($this->cache->containsEntity(TravelerProfile::CLASSNAME, $entity1->getId()));
|
||||||
|
$this->assertFalse($this->cache->containsEntity(TravelerProfile::CLASSNAME, $entity2->getId()));
|
||||||
|
$this->assertFalse($this->cache->containsEntity(TravelerProfileInfo::CLASSNAME, $entity1->getInfo()->getId()));
|
||||||
|
$this->assertFalse($this->cache->containsEntity(TravelerProfileInfo::CLASSNAME, $entity2->getInfo()->getId()));
|
||||||
|
|
||||||
|
$p1 = $this->_em->find(TravelerProfile::CLASSNAME, $entity1->getId());
|
||||||
|
$p2 = $this->_em->find(TravelerProfile::CLASSNAME, $entity2->getId());
|
||||||
|
|
||||||
|
$this->assertEquals($entity1->getId(), $p1->getId());
|
||||||
|
$this->assertEquals($entity1->getName(), $p1->getName());
|
||||||
|
$this->assertEquals($entity1->getInfo()->getId(), $p1->getInfo()->getId());
|
||||||
|
$this->assertEquals($entity1->getInfo()->getDescription(), $p1->getInfo()->getDescription());
|
||||||
|
|
||||||
|
$this->assertEquals($entity2->getId(), $p2->getId());
|
||||||
|
$this->assertEquals($entity2->getName(), $p2->getName());
|
||||||
|
$this->assertEquals($entity2->getInfo()->getId(), $p2->getInfo()->getId());
|
||||||
|
$this->assertEquals($entity2->getInfo()->getDescription(), $p2->getInfo()->getDescription());
|
||||||
|
|
||||||
|
$this->assertTrue($this->cache->containsEntity(TravelerProfile::CLASSNAME, $entity1->getId()));
|
||||||
|
$this->assertTrue($this->cache->containsEntity(TravelerProfile::CLASSNAME, $entity2->getId()));
|
||||||
|
$this->assertTrue($this->cache->containsEntity(TravelerProfileInfo::CLASSNAME, $entity1->getInfo()->getId()));
|
||||||
|
$this->assertTrue($this->cache->containsEntity(TravelerProfileInfo::CLASSNAME, $entity2->getInfo()->getId()));
|
||||||
|
|
||||||
|
$this->_em->clear();
|
||||||
|
|
||||||
|
$queryCount = $this->getCurrentQueryCount();
|
||||||
|
|
||||||
|
$p3 = $this->_em->find(TravelerProfile::CLASSNAME, $entity1->getId());
|
||||||
|
$p4 = $this->_em->find(TravelerProfile::CLASSNAME, $entity2->getId());
|
||||||
|
|
||||||
|
$this->assertInstanceOf(TravelerProfile::CLASSNAME, $p3);
|
||||||
|
$this->assertInstanceOf(TravelerProfile::CLASSNAME, $p4);
|
||||||
|
$this->assertInstanceOf(TravelerProfileInfo::CLASSNAME, $p3->getInfo());
|
||||||
|
$this->assertInstanceOf(TravelerProfileInfo::CLASSNAME, $p4->getInfo());
|
||||||
|
|
||||||
|
$this->assertEquals($entity1->getId(), $p3->getId());
|
||||||
|
$this->assertEquals($entity1->getName(), $p3->getName());
|
||||||
|
$this->assertEquals($entity1->getInfo()->getId(), $p3->getInfo()->getId());
|
||||||
|
$this->assertEquals($entity1->getInfo()->getDescription(), $p3->getInfo()->getDescription());
|
||||||
|
|
||||||
|
$this->assertEquals($entity2->getId(), $p4->getId());
|
||||||
|
$this->assertEquals($entity2->getName(), $p4->getName());
|
||||||
|
$this->assertEquals($entity2->getInfo()->getId(), $p4->getInfo()->getId());
|
||||||
|
$this->assertEquals($entity2->getInfo()->getDescription(), $p4->getInfo()->getDescription());
|
||||||
|
|
||||||
|
$this->assertEquals($queryCount, $this->getCurrentQueryCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -171,6 +171,8 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
|
|||||||
'Doctrine\Tests\Models\Cache\State',
|
'Doctrine\Tests\Models\Cache\State',
|
||||||
'Doctrine\Tests\Models\Cache\City',
|
'Doctrine\Tests\Models\Cache\City',
|
||||||
'Doctrine\Tests\Models\Cache\Traveler',
|
'Doctrine\Tests\Models\Cache\Traveler',
|
||||||
|
'Doctrine\Tests\Models\Cache\TravelerProfileInfo',
|
||||||
|
'Doctrine\Tests\Models\Cache\TravelerProfile',
|
||||||
'Doctrine\Tests\Models\Cache\Travel',
|
'Doctrine\Tests\Models\Cache\Travel',
|
||||||
'Doctrine\Tests\Models\Cache\Attraction',
|
'Doctrine\Tests\Models\Cache\Attraction',
|
||||||
'Doctrine\Tests\Models\Cache\Restaurant',
|
'Doctrine\Tests\Models\Cache\Restaurant',
|
||||||
@ -325,6 +327,8 @@ abstract class OrmFunctionalTestCase extends OrmTestCase
|
|||||||
$conn->executeUpdate('DELETE FROM cache_attraction');
|
$conn->executeUpdate('DELETE FROM cache_attraction');
|
||||||
$conn->executeUpdate('DELETE FROM cache_travel');
|
$conn->executeUpdate('DELETE FROM cache_travel');
|
||||||
$conn->executeUpdate('DELETE FROM cache_traveler');
|
$conn->executeUpdate('DELETE FROM cache_traveler');
|
||||||
|
$conn->executeUpdate('DELETE FROM cache_traveler_profile_info');
|
||||||
|
$conn->executeUpdate('DELETE FROM cache_traveler_profile');
|
||||||
$conn->executeUpdate('DELETE FROM cache_city');
|
$conn->executeUpdate('DELETE FROM cache_city');
|
||||||
$conn->executeUpdate('DELETE FROM cache_state');
|
$conn->executeUpdate('DELETE FROM cache_state');
|
||||||
$conn->executeUpdate('DELETE FROM cache_country');
|
$conn->executeUpdate('DELETE FROM cache_country');
|
||||||
|
Loading…
x
Reference in New Issue
Block a user