doctrine/doctrine2 — pull request #808 by FabioBatSilva (2013-10-01 15:54:02+00:00)
Title: Second level cache

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
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
createQuery('SELECT s FROM Entity\State s ORDER BY s.name')
->setCacheable(true)
->getResult();

```