1
0
mirror of synced 2024-12-05 03:06:05 +03:00
This commit is contained in:
fabios 2013-10-17 12:11:56 -04:00
parent d135e402bb
commit fb98277783
17 changed files with 80 additions and 64 deletions

View File

@ -2,7 +2,7 @@ The Second Level Cache
======================
The Second Level Cache is designed to reduce the amount of necessary database access.
It sits between your application and the database to avoid the number of database hits as many as possible.
It sits between your application and the database to avoid the number of database hits as much as possible.
When turned on, entities will be first searched in cache and if they are not found,
a database query will be fired an then the entity result will be stored in a cache provider.
@ -22,6 +22,9 @@ Each entity class, collection association and query has its region, where values
Caching Regions are specific region into the cache provider that might store entities, collection or queries.
Each cache region resides in a specific cache namespace and has its own lifetime configuration.
Notice that when caching collection and queries only identifiers are stored.
The entity values will be stored in its own region
Something like below for an entity region :
.. code-block:: php
@ -60,8 +63,7 @@ A query region might be something like :
.. note::
Notice that when caching collection and queries only identifiers are stored.
The entity values will be stored in its own region
The following data structures represents now the cache will looks like, this is not actual cached data.
.. _reference-second-level-cache-regions:
@ -80,6 +82,11 @@ It allows you to provide your own cache implementation that might take advantage
If you want to support locking for ``READ_WRITE`` strategies you should implement ``ConcurrentRegion``; ``CacheRegion`` otherwise.
Cache region
~~~~~~~~~~~~
Defines a contract for accessing a particular region.
``Doctrine\ORM\Cache\Region``
Defines a contract for accessing a particular cache region.
@ -111,7 +118,7 @@ Defines a contract for accessing a particular cache region.
*
* @param \Doctrine\ORM\Cache\CacheKey $key The key of the item to be retrieved.
*
* @return \Doctrine\ORM\Cache\CacheEntry The cached entry or NULL
* @return \Doctrine\ORM\Cache\CacheEntry|null The cached entry or NULL
*/
public function get(CacheKey $key);
@ -138,6 +145,14 @@ Defines a contract for accessing a particular cache region.
}
Concurrent cache region
~~~~~~~~~~~~~~~~~~~~~~~
A ``Doctrine\ORM\Cache\ConcurrentRegion`` is designed to store concurrently managed data region.
By default, Doctrine provides a very simple implementation based on file locks ``Doctrine\ORM\Cache\Region\FileLockRegion``.
If you want to use an ``READ_WRITE`` cache, you should consider providing your own cache region.
``Doctrine\ORM\Cache\ConcurrentRegion``
Defines contract for concurrently managed data region.
@ -166,6 +181,9 @@ Defines contract for concurrently managed data region.
public function unlock(CacheKey $key, Lock $lock);
}
Cache region
~~~~~~~~~~~~
``Doctrine\ORM\Cache\TimestampRegion``
Tracks the timestamps of the most recent updates to particular entity.
@ -179,7 +197,7 @@ Tracks the timestamps of the most recent updates to particular entity.
/**
* Update an specific key into the cache region.
*
* @param \Doctrine\ORM\Cache\CacheKey $key The key of the item to lock.
* @param \Doctrine\ORM\Cache\CacheKey $key The key of the item to update the timestamp.
*
* @throws \Doctrine\ORM\Cache\LockException Indicates a problem accessing the region.
*/
@ -364,8 +382,8 @@ To specify a default lifetime for all regions or specify a different lifetime fo
$regionConfig = $cacheConfig->getRegionsConfiguration();
//Cache Region lifetime
$regionConfig->setLifetime('my_entity_region', 3600);
$regionConfig->setDefaultLifetime(7200);
$regionConfig->setLifetime('my_entity_region', 3600); // Time to live for a specific region; In seconds
$regionConfig->setDefaultLifetime(7200); // Default time to live; In seconds
Cache Log
@ -672,7 +690,7 @@ Basic entity cache
$em->clear(); // Clear entity manager
$country = $em->find('Country', 1); // Retrieve item from cache
$country1 = $em->find('Country', 1); // Retrieve item from cache
$country->setName("New Name");
$em->persist($state);
@ -680,7 +698,8 @@ Basic entity cache
$em->clear(); // Clear entity manager
$country = $em->find('Country', 1); // Retrieve item from cache
$country2 = $em->find('Country', 1); // Retrieve item from cache
// Notice that $country1 and $country2 are not the same instance.
Association cache
@ -759,6 +778,8 @@ The query cache stores the results of the query but as identifiers, entity value
->setCacheable(true)
->getResult();
$em->clear()
// Check if query result is valid and load entities from cache
$result2 = $em->createQuery('SELECT c FROM Country c ORDER BY c.name')
->setCacheable(true)
@ -806,15 +827,16 @@ Using the last update timestamps as part of the query key invalidate the cache k
$entities = $em->getRepository('Entity\Country')->findAll();
// load from query and entities from cache..
$entities = $em->getRepository('Country')->findAll();
$entities = $em->getRepository('Entity\Country')->findAll();
// update the timestamp cache region for Country
$em->persist(new Country('zombieland'));
$em->flush();
$em->clear();
// Reload the query from database.
$entities = $em->getRepository('Country')->findAll();
// Reload from database.
// At this point the query cache key if not logger valid, the select goes straight
$entities = $em->getRepository('Entity\Country')->findAll();
Cache API
---------
@ -843,8 +865,9 @@ Limitations
Composite primary key
~~~~~~~~~~~~~~~~~~~~~
Composite primary key are supported by second level cache, however when one of the keys is an association
the cached entity should always be retrieved using the association identifier.
Composite primary key are supported by second level cache,
however when one of the keys is an association the cached entity should always be retrieved using the association identifier.
For performance reasons the cache API does not extract from composite primary key.
.. code-block:: php
@ -871,29 +894,19 @@ the cached entity should always be retrieved using the association identifier.
// Supported
/** @var $article Article */
$article = $this->_em->find("Article", 1);
$article = $em->find('Article', 1);
// Supported
/** @var $article Article */
$article = $this->_em->find("Article", $article);
$article = $em->find('Article', $article);
// Supported
$id = array('source' => 1, 'target' => 2);
$reference = $this->_em->find("Reference", $id);
$reference = $em->find('Reference', $id);
// NOT Supported
$id = array('source' => new Article(1), 'target' => new Article(2));
$reference = $this->_em->find("Reference", $id);
Concurrent cache region
~~~~~~~~~~~~~~~~~~~~~~~
A ``Doctrine\\ORM\\Cache\\ConcurrentRegion`` is designed to store concurrently managed data region.
By default, Doctrine provides a very simple implementation based on file locks ``Doctrine\\ORM\\Cache\\Region\\FileLockRegion``.
If you want to use an ``READ_WRITE`` cache, you should consider providing your own cache region.
for more details about how to implement a cache region please see :ref:`reference-second-level-cache-regions`
$reference = $em->find('Reference', $id);
DELETE / UPDATE queries

View File

@ -137,19 +137,19 @@ abstract class AbstractQuery
/**
* Second level cache region name.
*
* @var string
* @var string|null
*/
protected $cacheRegion;
/**
* Second level query cache mode.
*
* @var integer
* @var integer|null
*/
protected $cacheMode;
/**
* @var \Doctrine\ORM\Cache\Logging\CacheLogger
* @var \Doctrine\ORM\Cache\Logging\CacheLogger|null
*/
protected $cacheLogger;
@ -206,7 +206,7 @@ abstract class AbstractQuery
*/
public function setCacheRegion($cacheRegion)
{
$this->cacheRegion = $cacheRegion;
$this->cacheRegion = (string) $cacheRegion;
return $this;
}
@ -245,7 +245,7 @@ abstract class AbstractQuery
*/
public function setLifetime($lifetime)
{
$this->lifetime = $lifetime;
$this->lifetime = (integer) $lifetime;
return $this;
}
@ -264,7 +264,7 @@ abstract class AbstractQuery
*/
public function setCacheMode($cacheMode)
{
$this->cacheMode = $cacheMode;
$this->cacheMode = (integer) $cacheMode;
return $this;
}

View File

@ -165,7 +165,7 @@ interface Cache
/**
* Evicts all cached query results under the given name, or default query cache if the region name is NULL.
*
* @param string $regionName The cache name associated to the queries being cached.
* @param string|null $regionName The cache name associated to the queries being cached.
*/
public function evictQueryRegion($regionName = null);
@ -179,9 +179,9 @@ interface Cache
/**
* Get query cache by region name or create a new one if none exist.
*
* @param regionName Query cache region name, or default query cache if the region name is NULL.
* @param string|null $regionName Query cache region name, or default query cache if the region name is NULL.
*
* @return \Doctrine\ORM\Cache\QueryCache The Query Cache associated with the region name.
*/
public function getQueryCache($regionName = null);
}
}

View File

@ -35,22 +35,22 @@ use Doctrine\ORM\Cache\TimestampQueryCacheValidator;
class CacheConfiguration
{
/**
* @var \Doctrine\ORM\Cache\CacheFactory
* @var \Doctrine\ORM\Cache\CacheFactory|null
*/
private $cacheFactory;
/**
* @var \Doctrine\ORM\Cache\RegionsConfiguration
* @var \Doctrine\ORM\Cache\RegionsConfiguration|null
*/
private $regionsConfig;
/**
* @var \Doctrine\ORM\Cache\Logging\CacheLogger
* @var \Doctrine\ORM\Cache\Logging\CacheLogger|null
*/
private $cacheLogger;
/**
* @var \Doctrine\ORM\Cache\QueryCacheValidator
* @var \Doctrine\ORM\Cache\QueryCacheValidator|null
*/
private $queryValidator;

View File

@ -51,7 +51,7 @@ class DefaultCache implements Cache
private $cacheFactory;
/**
* @var array<\Doctrine\ORM\Cache\QueryCache>
* @var \Doctrine\ORM\Cache\QueryCache[]
*/
private $queryCaches = array();

View File

@ -57,17 +57,17 @@ class DefaultCacheFactory implements CacheFactory
private $regionsConfig;
/**
* @var \Doctrine\ORM\Cache\TimestampRegion
* @var \Doctrine\ORM\Cache\TimestampRegion|null
*/
private $timestampRegion;
/**
* @var array
* @var \Doctrine\ORM\Cache\Region[]
*/
private $regions;
private $regions = array();
/**
* @var string
* @var string|null
*/
private $fileLockRegionDirectory;
@ -86,7 +86,7 @@ class DefaultCacheFactory implements CacheFactory
*/
public function setFileLockRegionDirectory($fileLockRegionDirectory)
{
$this->fileLockRegionDirectory = $fileLockRegionDirectory;
$this->fileLockRegionDirectory = (string) $fileLockRegionDirectory;
}
/**
@ -200,7 +200,7 @@ class DefaultCacheFactory implements CacheFactory
if ($cache['usage'] === ClassMetadata::CACHE_USAGE_READ_WRITE) {
if ( ! $this->fileLockRegionDirectory) {
throw new \RuntimeException(
throw new \LogicException(
'If you want to use a "READ_WRITE" cache an implementation of "Doctrine\ORM\Cache\ConcurrentRegion" is required, ' .
'The default implementation provided by doctrine is "Doctrine\ORM\Cache\Region\FileLockRegion" if you what to use it please provide a valid directory, DefaultCacheFactory#setFileLockRegionDirectory(). '
);

View File

@ -51,7 +51,7 @@ interface Region
*
* @param \Doctrine\ORM\Cache\CacheKey $key The key of the item to be retrieved.
*
* @return \Doctrine\ORM\Cache\CacheEntry The cached entry or NULL
* @return \Doctrine\ORM\Cache\CacheEntry|null The cached entry or NULL
*
* @throws \Doctrine\ORM\Cache\CacheException Indicates a problem accessing the item or region.
*/

View File

@ -31,12 +31,12 @@ class RegionsConfiguration
/**
* @var array
*/
private $lifetimes;
private $lifetimes = array();
/**
* @var array
*/
private $lockLifetimes;
private $lockLifetimes = array();
/**
* @var integer
@ -54,8 +54,8 @@ class RegionsConfiguration
*/
public function __construct($defaultLifetime = 3600, $defaultLockLifetime = 60)
{
$this->defaultLifetime = $defaultLifetime;
$this->defaultLockLifetime = $defaultLockLifetime;
$this->defaultLifetime = (integer) $defaultLifetime;
$this->defaultLockLifetime = (integer) $defaultLockLifetime;
}
/**
@ -71,7 +71,7 @@ class RegionsConfiguration
*/
public function setDefaultLifetime($defaultLifetime)
{
$this->defaultLifetime = $defaultLifetime;
$this->defaultLifetime = (integer) $defaultLifetime;
}
/**
@ -87,7 +87,7 @@ class RegionsConfiguration
*/
public function setDefaultLockLifetime($defaultLockLifetime)
{
$this->defaultLockLifetime = $defaultLockLifetime;
$this->defaultLockLifetime = (integer) $defaultLockLifetime;
}
/**

View File

@ -31,7 +31,7 @@ interface TimestampRegion extends Region
/**
* Update an specific key into the cache region.
*
* @param \Doctrine\ORM\Cache\CacheKey $key The key of the item to lock.
* @param \Doctrine\ORM\Cache\CacheKey $key The key of the item to update the timestamp.
*
* @throws \Doctrine\ORM\Cache\LockException Indicates a problem accessing the region.
*/

View File

@ -41,4 +41,4 @@ final class Cache implements Annotation
* @var string Cache region name.
*/
public $region;
}
}

View File

@ -594,7 +594,7 @@ class ClassMetadataInfo implements ClassMetadata
/**
* @var array
*/
public $cache;
public $cache = null;
/**
* The ReflectionClass instance of the mapped class.
@ -875,7 +875,7 @@ class ClassMetadataInfo implements ClassMetadata
}
if ($this->cache) {
$serialized[] = "cache";
$serialized[] = 'cache';
}
return $serialized;

View File

@ -727,6 +727,8 @@ class XmlDriver extends FileDriver
}
/**
* Parse / Normalize the cache configuration
*
* @param SimpleXMLElement $cacheMapping
*
* @return array

View File

@ -732,6 +732,8 @@ class YamlDriver extends FileDriver
}
/**
* Parse / Normalize the cache configuration
*
* @param array $cacheMapping
*
* @return array

View File

@ -32,4 +32,4 @@ class CacheMetadataListener
$metadata->enableAssociationCache($mapping['fieldName'], $cache);
}
}
}
}

View File

@ -7,4 +7,4 @@ use Doctrine\ORM\Cache\CacheEntry;
class CacheEntryMock extends \ArrayObject implements CacheEntry
{
}
}

View File

@ -6,9 +6,8 @@ use Doctrine\ORM\Cache\CacheKey;
class CacheKeyMock extends CacheKey
{
function __construct($hash)
{
$this->hash = $hash;
}
}
}

View File

@ -252,7 +252,7 @@ class DefaultCacheFactoryTest extends OrmTestCase
}
/**
* @expectedException RuntimeException
* @expectedException LogicException
* @expectedExceptionMessage If you want to use a "READ_WRITE" cache an implementation of "Doctrine\ORM\Cache\ConcurrentRegion" is required, The default implementation provided by doctrine is "Doctrine\ORM\Cache\Region\FileLockRegion" if you what to use it please provide a valid directory
*/
public function testInvalidFileLockRegionDirectoryException()