-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Hotfix/#1169 extra lazy one to many should not delete referenced entities #1281
Changes from all commits
db36974
c2b3348
f184956
aed01ea
15397bb
43f301f
ed0331d
ff986a9
a8796fa
99c5650
6a2b7c2
d443d4f
b7b716a
01a9dad
7e85c94
cb780e8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,6 +23,7 @@ | |
use Doctrine\Common\Collections\Criteria; | ||
use Doctrine\ORM\Cache\EntityCacheKey; | ||
use Doctrine\ORM\Cache\CollectionCacheKey; | ||
use Doctrine\ORM\Cache\Persister\Entity\CachedEntityPersister; | ||
use Doctrine\ORM\Persisters\Collection\CollectionPersister; | ||
use Doctrine\ORM\PersistentCollection; | ||
use Doctrine\ORM\EntityManagerInterface; | ||
|
@@ -162,13 +163,13 @@ public function loadCollectionCache(PersistentCollection $collection, Collection | |
*/ | ||
public function storeCollectionCache(CollectionCacheKey $key, $elements) | ||
{ | ||
/* @var $targetPersister CachedEntityPersister */ | ||
$targetPersister = $this->uow->getEntityPersister($this->targetEntity->rootEntityName); | ||
$targetRegion = $targetPersister->getCacheRegion(); | ||
$targetHydrator = $targetPersister->getEntityHydrator(); | ||
$entry = $this->hydrator->buildCacheEntry($this->targetEntity, $key, $elements); | ||
|
||
foreach ($entry->identifiers as $index => $entityKey) { | ||
|
||
if ($targetRegion->contains($entityKey)) { | ||
continue; | ||
} | ||
|
@@ -238,15 +239,13 @@ public function get(PersistentCollection $collection, $index) | |
*/ | ||
public function removeElement(PersistentCollection $collection, $element) | ||
{ | ||
return $this->persister->removeElement($collection, $element); | ||
} | ||
if ($persisterResult = $this->persister->removeElement($collection, $element)) { | ||
$this->evictCollectionCache($collection); | ||
$this->evictElementCache($this->sourceEntity->rootEntityName, $collection->getOwner()); | ||
$this->evictElementCache($this->targetEntity->rootEntityName, $element); | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function removeKey(PersistentCollection $collection, $key) | ||
{ | ||
return $this->persister->removeKey($collection, $key); | ||
return $persisterResult; | ||
} | ||
|
||
/** | ||
|
@@ -264,4 +263,42 @@ public function loadCriteria(PersistentCollection $collection, Criteria $criteri | |
{ | ||
return $this->persister->loadCriteria($collection, $criteria); | ||
} | ||
|
||
/** | ||
* Clears cache entries related to the current collection | ||
* | ||
* @param PersistentCollection $collection | ||
*/ | ||
protected function evictCollectionCache(PersistentCollection $collection) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I figured that none of the |
||
{ | ||
$key = new CollectionCacheKey( | ||
$this->sourceEntity->rootEntityName, | ||
$this->association['fieldName'], | ||
$this->uow->getEntityIdentifier($collection->getOwner()) | ||
); | ||
|
||
$this->region->evict($key); | ||
|
||
if ($this->cacheLogger) { | ||
$this->cacheLogger->collectionCachePut($this->regionName, $key); | ||
} | ||
} | ||
|
||
/** | ||
* @param string $targetEntity | ||
* @param object $element | ||
*/ | ||
protected function evictElementCache($targetEntity, $element) | ||
{ | ||
/* @var $targetPersister CachedEntityPersister */ | ||
$targetPersister = $this->uow->getEntityPersister($targetEntity); | ||
$targetRegion = $targetPersister->getCacheRegion(); | ||
$key = new EntityCacheKey($targetEntity, $this->uow->getEntityIdentifier($element)); | ||
|
||
$targetRegion->evict($key); | ||
|
||
if ($this->cacheLogger) { | ||
$this->cacheLogger->entityCachePut($targetRegion->getName(), $key); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,6 +20,7 @@ | |
namespace Doctrine\ORM\Persisters\Collection; | ||
|
||
use Doctrine\Common\Collections\Criteria; | ||
use Doctrine\Common\Proxy\Proxy; | ||
use Doctrine\ORM\PersistentCollection; | ||
|
||
/** | ||
|
@@ -163,7 +164,20 @@ public function removeElement(PersistentCollection $collection, $element) | |
$mapping = $collection->getMapping(); | ||
$persister = $this->uow->getEntityPersister($mapping['targetEntity']); | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this was intended to be used only be used with |
||
return $persister->delete($element); | ||
$targetMetadata = $this->em->getClassMetadata($mapping['targetEntity']); | ||
|
||
if ($element instanceof Proxy && ! $element->__isInitialized()) { | ||
$element->__load(); | ||
} | ||
|
||
// clearing owning side value | ||
$targetMetadata->reflFields[$mapping['mappedBy']]->setValue($element, null); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This allows the "inverse" side to change the "owning-side", which is exactly what we didn't want to do. |
||
|
||
$this->uow->computeChangeSet($targetMetadata, $element); | ||
|
||
$persister->update($element); | ||
|
||
return true; | ||
} | ||
|
||
/** | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,8 @@ | |
*/ | ||
class Tweet | ||
{ | ||
const CLASSNAME = __CLASS__; | ||
|
||
/** | ||
* @Id | ||
* @GeneratedValue | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,6 +10,8 @@ | |
*/ | ||
class User | ||
{ | ||
const CLASSNAME = __CLASS__; | ||
|
||
/** | ||
* @Id | ||
* @GeneratedValue | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -240,22 +240,6 @@ public function testInvokeRemoveElement() | |
$this->assertFalse($persister->removeElement($collection, $element)); | ||
} | ||
|
||
public function testInvokeRemoveKey() | ||
{ | ||
$entity = new State("Foo"); | ||
$persister = $this->createPersisterDefault(); | ||
$collection = $this->createCollection($entity); | ||
|
||
$this->em->getUnitOfWork()->registerManaged($entity, array('id'=>1), array('id'=>1, 'name'=>'Foo')); | ||
|
||
$this->collectionPersister->expects($this->once()) | ||
->method('removeKey') | ||
->with($this->equalTo($collection), $this->equalTo(0)) | ||
->will($this->returnValue(false)); | ||
|
||
$this->assertFalse($persister->removeKey($collection, 0)); | ||
} | ||
|
||
public function testInvokeGet() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Method was dead/unused |
||
{ | ||
$entity = new State("Foo"); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Method was dead/unused