SecondCacheLevel association and inheritance update problem #5108

Closed
opened 2026-01-22 14:58:28 +01:00 by admin · 11 comments
Owner

Originally created by @mpoiriert on GitHub (Apr 19, 2016).

Originally assigned to: @lcobucci on GitHub.

I have a entities like this (I just document the minimum needed):


/**
 * @Entity
 * @Cache("NONSTRICT_READ_WRITE")
 * @DiscriminatorColumn(name="type", type="string")
 * @DiscriminatorMap({"child" = "ChildClass"})
 */
class BaseClass
{
}

/**
 * @Entity
 * @Cache("NONSTRICT_READ_WRITE")
 */
class ChildClass extends BaseClass
{
  /**
  * @Cache("NONSTRICT_READ_WRITE")
  */
  private $associations;
}

When changing the ChildClass->associations value and persisting it the data in the cache is not removed.

Investigating I found that the Doctrine\ORM\Cache\Persister\Entity\AbstractEntityPersister is using the entityName (that will be ChildClass) but that the Doctrine\ORM\Cache\Persister\Collection\NonStrictReadWriteCachedCollectionPersister is using the $this->sourceEntity->rootEntityName (that will be BaseClass) So it doesn't clear the proper key entry.

Pretty easy to change but might be risky...

If you consider that I am on the good track I can give it a try to make the unit test for it.

Originally created by @mpoiriert on GitHub (Apr 19, 2016). Originally assigned to: @lcobucci on GitHub. I have a entities like this (I just document the minimum needed): ``` php /** * @Entity * @Cache("NONSTRICT_READ_WRITE") * @DiscriminatorColumn(name="type", type="string") * @DiscriminatorMap({"child" = "ChildClass"}) */ class BaseClass { } /** * @Entity * @Cache("NONSTRICT_READ_WRITE") */ class ChildClass extends BaseClass { /** * @Cache("NONSTRICT_READ_WRITE") */ private $associations; } ``` When changing the ChildClass->associations value and persisting it the data in the cache is not removed. Investigating I found that the **Doctrine\ORM\Cache\Persister\Entity\AbstractEntityPersister** is using the **entityName** (that will be **ChildClass**) but that the **Doctrine\ORM\Cache\Persister\Collection\NonStrictReadWriteCachedCollectionPersister** is using the **$this->sourceEntity->rootEntityName** (that will be **BaseClass**) So it doesn't clear the proper key entry. Pretty easy to change but might be risky... If you consider that I am on the good track I can give it a try to make the unit test for it.
admin added the BugDuplicate labels 2026-01-22 14:58:28 +01:00
admin closed this issue 2026-01-22 14:58:28 +01:00
Author
Owner

@Metabor commented on GitHub (May 9, 2016):

Looks for me similar to the problem reported here:
https://github.com/doctrine/doctrine2/issues/5562

@Metabor commented on GitHub (May 9, 2016): Looks for me similar to the problem reported here: https://github.com/doctrine/doctrine2/issues/5562
Author
Owner

@mpoiriert commented on GitHub (May 9, 2016):

Yes i think the the problem is the same thing since both is related to inheritance and second level cache.

@mpoiriert commented on GitHub (May 9, 2016): Yes i think the the problem is the same thing since both is related to inheritance and second level cache.
Author
Owner

@duytbp commented on GitHub (Sep 27, 2016):

Hi all, is there any update on this bug?

@duytbp commented on GitHub (Sep 27, 2016): Hi all, is there any update on this bug?
Author
Owner

@lcobucci commented on GitHub (Sep 27, 2016):

I believe that #6028 fixes this.

@lcobucci commented on GitHub (Sep 27, 2016): I believe that #6028 fixes this.
Author
Owner

@mpoiriert commented on GitHub (Sep 27, 2016):

No it doesn't

@mpoiriert commented on GitHub (Sep 27, 2016): No it doesn't
Author
Owner

@lcobucci commented on GitHub (Sep 27, 2016):

@mpoiriert weird, what kind of associations do you have? I can investigate this today.

@lcobucci commented on GitHub (Sep 27, 2016): @mpoiriert weird, what kind of associations do you have? I can investigate this today.
Author
Owner

@mpoiriert commented on GitHub (Nov 1, 2016):

Sorry for the delay really busy at the time.

This is the class override I have to fix the issue on my side

use Doctrine\ORM\Cache\CollectionCacheKey;
use Doctrine\ORM\PersistentCollection;

/**
 * This is to fix this bug:
 * @see https://github.com/doctrine/doctrine2/issues/5793
 */
class NonStrictReadWriteCachedCollectionPersister extends \Doctrine\ORM\Cache\Persister\Collection\NonStrictReadWriteCachedCollectionPersister
{
    /**
     * {@inheritdoc}
     */
    public function delete(PersistentCollection $collection)
    {
        $ownerId = $this->uow->getEntityIdentifier($collection->getOwner());
        $key     = new CollectionCacheKey($this->sourceEntity->name, $this->association['fieldName'], $ownerId);

        $this->persister->delete($collection);

        $this->queuedCache['delete'][spl_object_hash($collection)] = $key;
    }

    /**
     * {@inheritdoc}
     */
    public function update(PersistentCollection $collection)
    {
        $isInitialized = $collection->isInitialized();
        $isDirty       = $collection->isDirty();

        if ( ! $isInitialized && ! $isDirty) {
            return;
        }

        $ownerId = $this->uow->getEntityIdentifier($collection->getOwner());
        $key     = new CollectionCacheKey($this->sourceEntity->name, $this->association['fieldName'], $ownerId);

       // Invalidate non initialized collections OR ordered collection
        if ($isDirty && ! $isInitialized || isset($this->association['orderBy'])) {
            $this->persister->update($collection);

            $this->queuedCache['delete'][spl_object_hash($collection)] = $key;

            return;
        }

        $this->persister->update($collection);

        $this->queuedCache['update'][spl_object_hash($collection)] = array(
            'key'   => $key,
            'list'  => $collection
        );
    }
}

and

use Doctrine\ORM\Cache\CollectionCacheKey;
use Doctrine\ORM\PersistentCollection;

/**
 * This is to fix this bug:
 * @see https://github.com/doctrine/doctrine2/issues/5793
 */
class ReadWriteCachedCollectionPersister extends \Doctrine\ORM\Cache\Persister\Collection\ReadWriteCachedCollectionPersister
{
    /**
     * {@inheritdoc}
     */
    public function delete(PersistentCollection $collection)
    {
        $ownerId = $this->uow->getEntityIdentifier($collection->getOwner());
        $key     = new CollectionCacheKey($this->sourceEntity->name, $this->association['fieldName'], $ownerId);
        $lock    = $this->region->lock($key);

        $this->persister->delete($collection);

        if ($lock === null) {
            return;
        }

        $this->queuedCache['delete'][spl_object_hash($collection)] = array(
            'key'   => $key,
            'lock'  => $lock
        );
    }

    /**
     * {@inheritdoc}
     */
    public function update(PersistentCollection $collection)
    {
        $isInitialized = $collection->isInitialized();
        $isDirty       = $collection->isDirty();

        if ( ! $isInitialized && ! $isDirty) {
            return;
        }

        $this->persister->update($collection);

        $ownerId = $this->uow->getEntityIdentifier($collection->getOwner());
        $key     = new CollectionCacheKey($this->sourceEntity->name, $this->association['fieldName'], $ownerId);
        $lock    = $this->region->lock($key);

        if ($lock === null) {
            return;
        }

        $this->queuedCache['update'][spl_object_hash($collection)] = array(
            'key'   => $key,
            'lock'  => $lock
        );
    }
}

As you can see the only thing I had to change is to use

$this->sourceEntity->name

instead of

$this->sourceEntity->rootEntityName

I never did a pull request with that fix since I didn't have time to follow protocol and I did want to make sure it's working. We are using this fix since the 20th April

@mpoiriert commented on GitHub (Nov 1, 2016): Sorry for the delay really busy at the time. This is the class override I have to fix the issue on my side ``` use Doctrine\ORM\Cache\CollectionCacheKey; use Doctrine\ORM\PersistentCollection; /** * This is to fix this bug: * @see https://github.com/doctrine/doctrine2/issues/5793 */ class NonStrictReadWriteCachedCollectionPersister extends \Doctrine\ORM\Cache\Persister\Collection\NonStrictReadWriteCachedCollectionPersister { /** * {@inheritdoc} */ public function delete(PersistentCollection $collection) { $ownerId = $this->uow->getEntityIdentifier($collection->getOwner()); $key = new CollectionCacheKey($this->sourceEntity->name, $this->association['fieldName'], $ownerId); $this->persister->delete($collection); $this->queuedCache['delete'][spl_object_hash($collection)] = $key; } /** * {@inheritdoc} */ public function update(PersistentCollection $collection) { $isInitialized = $collection->isInitialized(); $isDirty = $collection->isDirty(); if ( ! $isInitialized && ! $isDirty) { return; } $ownerId = $this->uow->getEntityIdentifier($collection->getOwner()); $key = new CollectionCacheKey($this->sourceEntity->name, $this->association['fieldName'], $ownerId); // Invalidate non initialized collections OR ordered collection if ($isDirty && ! $isInitialized || isset($this->association['orderBy'])) { $this->persister->update($collection); $this->queuedCache['delete'][spl_object_hash($collection)] = $key; return; } $this->persister->update($collection); $this->queuedCache['update'][spl_object_hash($collection)] = array( 'key' => $key, 'list' => $collection ); } } ``` and ``` use Doctrine\ORM\Cache\CollectionCacheKey; use Doctrine\ORM\PersistentCollection; /** * This is to fix this bug: * @see https://github.com/doctrine/doctrine2/issues/5793 */ class ReadWriteCachedCollectionPersister extends \Doctrine\ORM\Cache\Persister\Collection\ReadWriteCachedCollectionPersister { /** * {@inheritdoc} */ public function delete(PersistentCollection $collection) { $ownerId = $this->uow->getEntityIdentifier($collection->getOwner()); $key = new CollectionCacheKey($this->sourceEntity->name, $this->association['fieldName'], $ownerId); $lock = $this->region->lock($key); $this->persister->delete($collection); if ($lock === null) { return; } $this->queuedCache['delete'][spl_object_hash($collection)] = array( 'key' => $key, 'lock' => $lock ); } /** * {@inheritdoc} */ public function update(PersistentCollection $collection) { $isInitialized = $collection->isInitialized(); $isDirty = $collection->isDirty(); if ( ! $isInitialized && ! $isDirty) { return; } $this->persister->update($collection); $ownerId = $this->uow->getEntityIdentifier($collection->getOwner()); $key = new CollectionCacheKey($this->sourceEntity->name, $this->association['fieldName'], $ownerId); $lock = $this->region->lock($key); if ($lock === null) { return; } $this->queuedCache['update'][spl_object_hash($collection)] = array( 'key' => $key, 'lock' => $lock ); } } ``` As you can see the only thing I had to change is to use `$this->sourceEntity->name` instead of `$this->sourceEntity->rootEntityName` I never did a pull request with that fix since I didn't have time to follow protocol and I did want to make sure it's working. We are using this fix since the 20th April
Author
Owner

@lcobucci commented on GitHub (Jan 19, 2017):

@mpoiriert did you try your mapping with 2.6.x-dev?
The persisters must use the rootEntityName so your fix might break something else we build.

You could also send us the mapping you have so we can try it out and find the problem.

@lcobucci commented on GitHub (Jan 19, 2017): @mpoiriert did you try your mapping with `2.6.x-dev`? The persisters must use the `rootEntityName` so your fix might break something else we build. You could also send us the mapping you have so we can try it out and find the problem.
Author
Owner

@lcobucci commented on GitHub (Jan 19, 2017):

@mpoiriert sorry, you were right that the problem wasn't solved.
I'm sending a PR today that fixes it for good 😉

@lcobucci commented on GitHub (Jan 19, 2017): @mpoiriert sorry, you were right that the problem wasn't solved. I'm sending a PR today that fixes it for good 😉
Author
Owner

@mpoiriert commented on GitHub (Jan 19, 2017):

Great thanks. We are planning to upgrade all our stack in the next couples of months so I'll be glad to remove all my factory/override when I'll pass to 2.6.0

@mpoiriert commented on GitHub (Jan 19, 2017): Great thanks. We are planning to upgrade all our stack in the next couples of months so I'll be glad to remove all my factory/override when I'll pass to 2.6.0
Author
Owner

@lcobucci commented on GitHub (Jan 19, 2017):

@mpoiriert nice, I'll close this issue since we merged #6244.
Would be amazing if you could test your mapping using 2.6.x-dev and report us any other issue.

@lcobucci commented on GitHub (Jan 19, 2017): @mpoiriert nice, I'll close this issue since we merged #6244. Would be amazing if you could test your mapping using `2.6.x-dev` and report us any other issue.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: doctrine/archived-orm#5108