Skip to content

Commit

Permalink
Fixed support for inverse side second levle cache
Browse files Browse the repository at this point in the history
  • Loading branch information
guilhermeblanco committed Nov 11, 2015
1 parent 1187c51 commit 13d1ec2
Show file tree
Hide file tree
Showing 8 changed files with 51 additions and 24 deletions.
1 change: 1 addition & 0 deletions lib/Doctrine/ORM/Cache/DefaultCollectionHydrator.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ public function buildCacheEntry(ClassMetadata $metadata, CollectionCacheKey $key
foreach ($collection as $index => $entity) {
$data[$index] = new EntityCacheKey($metadata->name, $this->uow->getEntityIdentifier($entity));
}

return new CollectionCacheEntry($data);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,10 +164,18 @@ public function loadCollectionCache(PersistentCollection $collection, Collection
public function storeCollectionCache(CollectionCacheKey $key, $elements)
{
/* @var $targetPersister CachedEntityPersister */
$associationMapping = $this->sourceEntity->associationMappings[$key->association];
$targetPersister = $this->uow->getEntityPersister($this->targetEntity->rootEntityName);
$targetRegion = $targetPersister->getCacheRegion();
$targetHydrator = $targetPersister->getEntityHydrator();
$entry = $this->hydrator->buildCacheEntry($this->targetEntity, $key, $elements);

// Only preserve ordering if association configured it
if ( ! (isset($associationMapping['orderBy']) && $associationMapping['orderBy'])) {
// Elements may be an array or a Collection
$elements = array_values(is_array($elements) ? $elements : $elements->getValues());
}

$entry = $this->hydrator->buildCacheEntry($this->targetEntity, $key, $elements);

foreach ($entry->identifiers as $index => $entityKey) {
if ($targetRegion->contains($entityKey)) {
Expand Down
8 changes: 2 additions & 6 deletions lib/Doctrine/ORM/UnitOfWork.php
Original file line number Diff line number Diff line change
Expand Up @@ -733,7 +733,6 @@ public function computeChangeSet(ClassMetadata $class, $entity)

// Look for changes in associations of the entity
foreach ($class->associationMappings as $field => $assoc) {

if (($val = $class->reflFields[$field]->getValue($entity)) === null) {
continue;
}
Expand Down Expand Up @@ -799,7 +798,7 @@ public function computeChangeSets()
// Only MANAGED entities that are NOT SCHEDULED FOR INSERTION OR DELETION are processed here.
$oid = spl_object_hash($entity);

if ( ! isset($this->entityInsertions[$oid]) && ! isset($this->entityDeletions[$oid]) && isset($this->entityStates[$oid])) {
if ( ! isset($this->entityInsertions[$oid]) && ! isset($this->entityDeletions[$oid]) && isset($this->entityStates[$oid])) {
$this->computeChangeSet($class, $entity);
}
}
Expand All @@ -826,10 +825,7 @@ private function computeAssociationChanges($assoc, $value)
if ($value instanceof PersistentCollection && $value->isDirty()) {
$coid = spl_object_hash($value);

if ($assoc['isOwningSide']) {
$this->collectionUpdates[$coid] = $value;
}

$this->collectionUpdates[$coid] = $value;
$this->visitedCollections[$coid] = $value;
}

Expand Down
2 changes: 1 addition & 1 deletion tests/Doctrine/Tests/Models/Cache/City.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
use Doctrine\Common\Collections\ArrayCollection;

/**
* @Cache
* @Entity
* @Table("cache_city")
* @Cache
*/
class City
{
Expand Down
2 changes: 1 addition & 1 deletion tests/Doctrine/Tests/Models/Cache/State.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class State
protected $country;

/**
* @Cache
* @Cache("NONSTRICT_READ_WRITE")
* @OneToMany(targetEntity="City", mappedBy="state")
*/
protected $cities;
Expand Down
2 changes: 1 addition & 1 deletion tests/Doctrine/Tests/Models/Cache/Traveler.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class Traveler
protected $name;

/**
* @Cache()
* @Cache("NONSTRICT_READ_WRITE")
* @OneToMany(targetEntity="Travel", mappedBy="traveler", cascade={"persist", "remove"}, orphanRemoval=true)
*
* @var \Doctrine\Common\Collections\Collection
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

namespace Doctrine\Tests\ORM\Functional;

use Doctrine\Tests\Models\Cache\City;
use Doctrine\Tests\Models\Cache\ComplexAction;
use Doctrine\Tests\Models\Cache\Country;
use Doctrine\Tests\Models\Cache\State;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\Tests\Models\Cache\Token;
use Doctrine\Tests\Models\Cache\Action;

Expand Down Expand Up @@ -96,6 +96,26 @@ public function testPutAndLoadManyToOneRelation()

$this->assertEquals($this->states[1]->getCountry()->getId(), $c4->getCountry()->getId());
$this->assertEquals($this->states[1]->getCountry()->getName(), $c4->getCountry()->getName());

//evict collection on add
$prev = $c3->getCities();
$count = $prev->count();
$city = new City("Buenos Aires", $c3);

$c3->addCity($city);

$this->_em->persist($city);
$this->_em->persist($c3);
$this->_em->flush();
$this->_em->clear();

$state = $this->_em->find(State::CLASSNAME, $c3->getId());

// Association was cleared from EM
$this->assertNotEquals($prev, $state->getCities());

// New association has one more item (cache was evicted)
$this->assertEquals($count + 1, $state->getCities()->count());
}

public function testShouldNotReloadWhenAssociationIsMissing()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,18 @@
*/
class SecondLevelCacheOneToManyTest extends SecondLevelCacheAbstractTest
{
public function testShouldNotPutCollectionInverseSideOnPersist()
public function testShouldPutCollectionInverseSideOnPersist()
{
$this->loadFixturesCountries();
$this->loadFixturesStates();
$this->loadFixturesCities();

$this->_em->clear();

$this->assertTrue($this->cache->containsEntity(State::CLASSNAME, $this->states[0]->getId()));
$this->assertTrue($this->cache->containsEntity(State::CLASSNAME, $this->states[1]->getId()));

$this->assertFalse($this->cache->containsCollection(State::CLASSNAME, 'cities', $this->states[0]->getId()));
$this->assertFalse($this->cache->containsCollection(State::CLASSNAME, 'cities', $this->states[1]->getId()));
$this->assertTrue($this->cache->containsCollection(State::CLASSNAME, 'cities', $this->states[0]->getId()));
$this->assertTrue($this->cache->containsCollection(State::CLASSNAME, 'cities', $this->states[1]->getId()));
}

public function testPutAndLoadOneToManyRelation()
Expand Down Expand Up @@ -187,6 +187,7 @@ public function testOneToManyRemove()
$this->loadFixturesCountries();
$this->loadFixturesStates();
$this->loadFixturesCities();

$this->_em->clear();
$this->secondLevelCacheLogger->clearStats();

Expand Down Expand Up @@ -247,8 +248,8 @@ public function testOneToManyRemove()
$this->_em->remove($city0);
$this->_em->persist($state);
$this->_em->flush();

$this->_em->clear();

$this->secondLevelCacheLogger->clearStats();

$queryCount = $this->getCurrentQueryCount();
Expand All @@ -261,29 +262,29 @@ public function testOneToManyRemove()
$this->assertInstanceOf(City::CLASSNAME, $city1);
$this->assertEquals($entity->getCities()->get(1)->getName(), $city1->getName());

$this->assertEquals(1, $this->secondLevelCacheLogger->getHitCount());
$this->assertEquals(2, $this->secondLevelCacheLogger->getHitCount());
$this->assertEquals(1, $this->secondLevelCacheLogger->getRegionHitCount($this->getEntityRegion(State::CLASSNAME)));
$this->assertEquals(0, $this->secondLevelCacheLogger->getRegionHitCount($this->getCollectionRegion(State::CLASSNAME, 'cities')));
$this->assertEquals(1, $this->secondLevelCacheLogger->getRegionHitCount($this->getCollectionRegion(State::CLASSNAME, 'cities')));

$this->assertEquals($queryCount + 1, $this->getCurrentQueryCount());
$this->assertEquals($queryCount, $this->getCurrentQueryCount());

$state->getCities()->remove(0);

$this->_em->remove($city1);
$this->_em->persist($state);
$this->_em->flush();

$this->_em->clear();

$this->secondLevelCacheLogger->clearStats();

$queryCount = $this->getCurrentQueryCount();
$state = $this->_em->find(State::CLASSNAME, $this->states[0]->getId());

$this->assertCount(0, $state->getCities());

$this->assertEquals(1, $this->secondLevelCacheLogger->getHitCount());
$this->assertEquals(2, $this->secondLevelCacheLogger->getHitCount());
$this->assertEquals(1, $this->secondLevelCacheLogger->getRegionHitCount($this->getEntityRegion(State::CLASSNAME)));
$this->assertEquals(0, $this->secondLevelCacheLogger->getRegionHitCount($this->getCollectionRegion(State::CLASSNAME, 'cities')));
$this->assertEquals(1, $this->secondLevelCacheLogger->getRegionHitCount($this->getCollectionRegion(State::CLASSNAME, 'cities')));
}

public function testOneToManyWithEmptyRelation()
Expand Down Expand Up @@ -346,11 +347,12 @@ public function testOneToManyCount()
public function testCacheInitializeCollectionWithNewObjects()
{
$this->_em->clear();

$this->evictRegions();

$traveler = new Traveler("Doctrine Bot");

for ($i=0; $i<3; ++$i) {
for ($i = 0; $i < 3; ++$i) {
$traveler->getTravels()->add(new Travel($traveler));
}

Expand All @@ -373,7 +375,7 @@ public function testCacheInitializeCollectionWithNewObjects()
$this->assertFalse($entity->getTravels()->isInitialized());
$this->assertCount(4, $entity->getTravels());
$this->assertTrue($entity->getTravels()->isInitialized());
$this->assertEquals($queryCount + 1, $this->getCurrentQueryCount());
$this->assertEquals($queryCount, $this->getCurrentQueryCount());

$this->_em->flush();
$this->_em->clear();
Expand Down

0 comments on commit 13d1ec2

Please sign in to comment.