DDC-2716: [GH-808] Second level cache #3401

Closed
opened 2026-01-22 14:19:14 +01:00 by admin · 2 comments
Owner

Originally created by @doctrinebot on GitHub (Oct 1, 2013).

Originally assigned to: @beberlei on GitHub.

Jira issue originally created by user @doctrinebot:

This issue is created automatically through a Github pull request on behalf of FabioBatSilva:

Url: https://github.com/doctrine/doctrine2/pull/808

Message:

Hi guys,

I believe, We are coming to an end.. ;)
https://github.com/doctrine/doctrine2/pull/580, rebase and reopened to make easier to final review.

Cache strategies

* READ_ONLY (DEFAULT)   : ReadOnly cache can do reads, inserts and deletes, cannot perform updates or employ any locks.
* NONSTRICT*READ*WRITE  : Nonstrict Read Write Cache doesn���t employ any locks but can do reads, inserts , updates and deletes.
* READ_WRITE            : Read Write cache employs locks the entity before update/delete.

classes / interfaces

** Region* :
Defines a contract for accessing a entity/collection data cache. (Doesn���t employ any locks)

** ConcurrentRegion* :
Defines contract for concurrently managed data region. (Locks the data before update/delete.)

* CacheKey / EntityCacheKey / CollectionCacheKey/ QueryCacheKey:
Defines entity / collection key to be stored in the cache region.

* EntityHidrator / CollectionHidrator
Build cache entries and rebuild entities/colection from cache

* CacheFactory
Factory from second level cache components

Collection Caching

The most common use case is to cache entities. But we can also cache relationships.
A ���collection cache��� caches the primary keys of entities that are members of a collection (OneToMany/ManyToMany).
and each element will be cached into its region.

Only identifiers will be cached for collection. When a collection is read from the second level cache it will create proxies based on the cached identifiers, if the application needs to access an element, Doctrine will go to the cache to load the element data.

Query Cache

The query cache does not cache the state of the actual entities in the result set;
it caches only identifier values for an individual query.
So the query cache should always be used in conjunction with the second-level cache.

OPERATIONS

INSERT :

***************************************************************************************************
                    | READ-ONLY             | NONSTRICT-READ-WRITE      | READ-WRITE            |
-------------------------------------------------------------------------------------------------
pre-insert          |                       |                           |                       |
-------------------------------------------------------------------------------------------------
on-insert           |                       |                           |                       |
-------------------------------------------------------------------------------------------------
after-transaction   | add item to the cache | add item to the cache     | add item to the cache |
-------------------------------------------------------------------------------------------------

UPDATE :

***************************************************************************************************
                    | READ-ONLY             | NONSTRICT-READ-WRITE      | READ-WRITE            |
-------------------------------------------------------------------------------------------------
pre-update          |                       |                           | lock item             |
-------------------------------------------------------------------------------------------------
on-update           | throws exception      |                           |                       |
-------------------------------------------------------------------------------------------------
after-transaction   |                       |  update item cache        | remove item cache     |
-------------------------------------------------------------------------------------------------

DELETE :

***************************************************************************************************
                    | READ-ONLY             | NONSTRICT-READ-WRITE      | READ-WRITE            |
-------------------------------------------------------------------------------------------------
pre-remove          |                       |                           |                       |
-------------------------------------------------------------------------------------------------
on-remove           |                       |                           | lock item             |
-------------------------------------------------------------------------------------------------
after-transaction   | remove item cache     |  remove item cache        | remove item cache     |
-------------------------------------------------------------------------------------------------

USAGE :

<?php

/****
 * @Entity
 * @Cache("NONSTRICT*READ*WRITE")
 */
class State
{
    /****
     * @Id
     * @GeneratedValue
     * @Column(type="integer")
     */
    protected $id;
    /****
     * @Column
     */
    protected $name;
    /****
     * @Cache()
     * @ManyToOne(targetEntity="Country")
     * @JoinColumn(name="country_id", referencedColumnName="id")
     */
    protected $country;
    /****
     * @Cache()
     * @OneToMany(targetEntity="City", mappedBy="state")
     */
    protected $cities;
}
<?php

$em->persist(new State($name, $country));
$em->flush();                                // Put into cache

$em->clear();                                // Clear entity manager

$state   = $em->find('Entity\State', 1);     // Retreive item from cache
$country = $state->getCountry();             // Retreive item from cache
$cities  = $state->getCities();              // Load from database and put into cache

$state->setName("New Name");
$em->persist($state);
$em->flush();                                // Update item cache

$em->clear();                                // Clear entity manager

$em->find('Entity\State', 1)->getCities();   // Retreive from cache


$em->getCache()->containsEntity('Entity\State', $state->getId())  // Check if the cache exists
$em->getCache()->evictEntity('Entity\State', $state->getId());    // Remove an entity from cache
$em->getCache()->evictEntityRegion('Entity\State');               // Remove all entities from cache

$em->getCache()->containsCollection('Entity\State', 'cities', $state->getId());   // Check if the cache exists        
$em->getCache()->evictCollection('Entity\State', 'cities', $state->getId());      // Remove an entity collection from cache
$em->getCache()->evictCollectionRegion('Entity\State', 'cities');                 // Remove all collections from cache

<?php

    // Execute database query, store query cache and entity cache into 2lc
    $result = $em->createQuery('SELECT s FROM Entity\State s ORDER BY s.name')
        ->setCacheable(true)
        ->getResult();

Originally created by @doctrinebot on GitHub (Oct 1, 2013). Originally assigned to: @beberlei on GitHub. Jira issue originally created by user @doctrinebot: This issue is created automatically through a Github pull request on behalf of FabioBatSilva: Url: https://github.com/doctrine/doctrine2/pull/808 Message: Hi guys, I believe, We are coming to an end.. ;) https://github.com/doctrine/doctrine2/pull/580, rebase and reopened to make easier to final review. ### Cache strategies ``` * READ_ONLY (DEFAULT) : ReadOnly cache can do reads, inserts and deletes, cannot perform updates or employ any locks. * NONSTRICT*READ*WRITE : Nonstrict Read Write Cache doesn���t employ any locks but can do reads, inserts , updates and deletes. * READ_WRITE : Read Write cache employs locks the entity before update/delete. ``` ### classes / interfaces *\* **Region**\* : Defines a contract for accessing a entity/collection data cache. (Doesn���t employ any locks) *\* **ConcurrentRegion**\* : Defines contract for concurrently managed data region. (Locks the data before update/delete.) *\* **CacheKey / EntityCacheKey / CollectionCacheKey/ QueryCacheKey***: Defines entity / collection key to be stored in the cache region. *\* **EntityHidrator / CollectionHidrator*** Build cache entries and rebuild entities/colection from cache *\* **CacheFactory*** Factory from second level cache components ### Collection Caching The most common use case is to cache entities. But we can also cache relationships. A ���collection cache��� caches the primary keys of entities that are members of a collection (OneToMany/ManyToMany). and each element will be cached into its region. Only identifiers will be cached for collection. When a collection is read from the second level cache it will create proxies based on the cached identifiers, if the application needs to access an element, Doctrine will go to the cache to load the element data. ### Query Cache The query cache does not cache the state of the actual entities in the result set; it caches only identifier values for an individual query. So the query cache should always be used in conjunction with the second-level cache. ### OPERATIONS #### INSERT : ``` *************************************************************************************************** | READ-ONLY | NONSTRICT-READ-WRITE | READ-WRITE | ------------------------------------------------------------------------------------------------- pre-insert | | | | ------------------------------------------------------------------------------------------------- on-insert | | | | ------------------------------------------------------------------------------------------------- after-transaction | add item to the cache | add item to the cache | add item to the cache | ------------------------------------------------------------------------------------------------- ``` #### UPDATE : ``` *************************************************************************************************** | READ-ONLY | NONSTRICT-READ-WRITE | READ-WRITE | ------------------------------------------------------------------------------------------------- pre-update | | | lock item | ------------------------------------------------------------------------------------------------- on-update | throws exception | | | ------------------------------------------------------------------------------------------------- after-transaction | | update item cache | remove item cache | ------------------------------------------------------------------------------------------------- ``` #### DELETE : ``` *************************************************************************************************** | READ-ONLY | NONSTRICT-READ-WRITE | READ-WRITE | ------------------------------------------------------------------------------------------------- pre-remove | | | | ------------------------------------------------------------------------------------------------- on-remove | | | lock item | ------------------------------------------------------------------------------------------------- after-transaction | remove item cache | remove item cache | remove item cache | ------------------------------------------------------------------------------------------------- ``` #### USAGE : ``` php <?php /**** * @Entity * @Cache("NONSTRICT*READ*WRITE") */ class State { /**** * @Id * @GeneratedValue * @Column(type="integer") */ protected $id; /**** * @Column */ protected $name; /**** * @Cache() * @ManyToOne(targetEntity="Country") * @JoinColumn(name="country_id", referencedColumnName="id") */ protected $country; /**** * @Cache() * @OneToMany(targetEntity="City", mappedBy="state") */ protected $cities; } ``` ``` php <?php $em->persist(new State($name, $country)); $em->flush(); // Put into cache $em->clear(); // Clear entity manager $state = $em->find('Entity\State', 1); // Retreive item from cache $country = $state->getCountry(); // Retreive item from cache $cities = $state->getCities(); // Load from database and put into cache $state->setName("New Name"); $em->persist($state); $em->flush(); // Update item cache $em->clear(); // Clear entity manager $em->find('Entity\State', 1)->getCities(); // Retreive from cache $em->getCache()->containsEntity('Entity\State', $state->getId()) // Check if the cache exists $em->getCache()->evictEntity('Entity\State', $state->getId()); // Remove an entity from cache $em->getCache()->evictEntityRegion('Entity\State'); // Remove all entities from cache $em->getCache()->containsCollection('Entity\State', 'cities', $state->getId()); // Check if the cache exists $em->getCache()->evictCollection('Entity\State', 'cities', $state->getId()); // Remove an entity collection from cache $em->getCache()->evictCollectionRegion('Entity\State', 'cities'); // Remove all collections from cache ``` ``` php <?php // Execute database query, store query cache and entity cache into 2lc $result = $em->createQuery('SELECT s FROM Entity\State s ORDER BY s.name') ->setCacheable(true) ->getResult(); ```
admin added the Bug label 2026-01-22 14:19:14 +01:00
admin closed this issue 2026-01-22 14:19:14 +01:00
Author
Owner

@doctrinebot commented on GitHub (Dec 16, 2013):

Comment created by @doctrinebot:

A related Github Pull-Request [GH-808] was closed:
https://github.com/doctrine/doctrine2/pull/808

@doctrinebot commented on GitHub (Dec 16, 2013): Comment created by @doctrinebot: A related Github Pull-Request [GH-808] was closed: https://github.com/doctrine/doctrine2/pull/808
Author
Owner

@doctrinebot commented on GitHub (Dec 16, 2013):

Issue was closed with resolution "Fixed"

@doctrinebot commented on GitHub (Dec 16, 2013): Issue was closed with resolution "Fixed"
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: doctrine/archived-orm#3401