878 words

Shared (L2) Entity Cache

Every EntityManagerjavax.persistence.EntityManagerJPA interfaceInterface used to interact with the persistence context.
See JavaDoc Reference Page...
owns a persistence context, which is a collection of all the entity objects that it manages. The persistence context serves as a first level cache. An attempt to retrieve an entity object that is already managed by the EntityManager returns the existing instance from the persistence context, rather than a new instantiated entity object.

The scope of the persistence context is one EntityManagerjavax.persistence.EntityManagerJPA interfaceInterface used to interact with the persistence context.
See JavaDoc Reference Page...
. This section describes a level 2  (L2) cache of entity objects, which is managed by the EntityManagerFactoryjavax.persistence.EntityManagerFactoryJPA interfaceInterface used to interact with the entity manager factory for the persistence unit.
See JavaDoc Reference Page...
and shared by all its EntityManager objects. the broader scope of this cache makes it useful in applications that use many short term EntityManager instances. 

In addition to the EntityManager's L1 cache and the EntityManagerFactory's L2 cache, which are managed on the client side - ObjectDB manages also several caches on the server side:

The scope of these server side caches is wider, since they exist per database and are shared by all the EntityManagerFactory and EntityManager instances of the same database - including on different client machines.

Setting the Shared Cache

The shared (L2) cache is configured in three scopes:

  • Globally in the ObjectDB configuration.
  • Per persistence unit in the persistence.xml file.
  • Per entity class - using annotations.

ObjectDB Configuration

The shared cache size is specified in the ObjectDB configuration

    <cache ... level2="0mb" />

The level2 attribute determines the size of the EntityManagerFactory's shared cache. The default size, 0, indicates that the cache is disabled. To enable the cache a positive value has to be specified.

Persistence Unit Settings

The shared cache can also be enabled or disabled using a persistence unit property:

   <persistence-unit name="my-pu">
     ...
     <properties>
       <property name="javax.persistence.sharedCache.mode" value="ALL"/>
     </properties>
     ...
   </persistence-unit>

The javax.persistence.sharedCache.mode property can be set to one of the following values:

  • NONE - cache is disabled.
  • ENABLE_SELECTIVE - cache is disabled except for selected entity classes (see below).
  • DISABLE_SELECTIVE - cache is enabled except for selected entity classes (see below).
  • ALL (the default) - cache is enabled for all the entity classes.
  • UNSPECIFIED - handled differently by different JPA providers. In ObjectDB the UNSPECIFIED value is equivalent to ALL, which is the default. 

If the cache size is 0 - the shared cache is disabled regardless of the set mode.

Entity Class Cache Settings

The ENABLE_SELECTIVE mode indicates that the cache is disabled for all the entity classes except classes that are specified as Cacheablejavax.persistence.CacheableJPA annotationSpecifies whether an entity should be cached if caching is enabled when the value of the persistence.xml caching element is ENABLE_SELECTIVE or DISABLE_SELECTIVE.
See JavaDoc Reference Page...
explicitly. For example:

Similarly, the DISABLE_SELECTIVE value indicates that the cache is enabled for all the entity classes except classes that are specified as non Cacheablejavax.persistence.CacheableJPA annotationSpecifies whether an entity should be cached if caching is enabled when the value of the persistence.xml caching element is ENABLE_SELECTIVE or DISABLE_SELECTIVE.
See JavaDoc Reference Page...
explicitly. For example:

Cacheable is an inherited property - every entity class which is not marked with @Cacheable inherits cacheability setting from its super class.

Using the Shared Cache

The shared cache (when enabled) provides the following functionality automatically:

  • On retrieval - shared cache is used for entity objects that are not in the persistence context. If an entity object is not available also in the shared cache - it is retrieved from the database and added to the shared cache.
  • On commit - new and modified entity objects are added to the shared cache.

JPA provides two properties that can be used in order to change the default behavior.

javax.persistence.cache.retrieveMode

The  "javax.persistence.cache.retrieveMode" property specifies if the shared cache is used on retrieval. Two values are available for this property as constants of the CacheRetrieveModejavax.persistence.CacheRetrieveModeJPA enumUsed as the value of the javax.persistence.cache.retrieveMode property to specify the behavior when data is retrieved by the find methods and by queries.
See JavaDoc Reference Page...
enum:

The default setting is USECacheRetrieveMode.USEenum constantRead entity data from the cache: this is the default behavior.
See JavaDoc Reference Page...
. It can be changed for a specific EntityManager:

Setting can also be overridden for a specific retrieval operation:

javax.persistence.cache.storeMode

The  "javax.persistence.cache.storeMode" property specifies if new data should be added to the cache on commit and on retrieval. The property has three valid values, which are defined as constants of the CacheStoreModejavax.persistence.CacheStoreModeJPA enumUsed as the value of the javax.persistence.cache.storeMode property to specify the behavior when data is read from the database and when data is committed into the database.
See JavaDoc Reference Page...
enum:

The default setting is USECacheStoreMode.USEenum constantInsert/update entity data into cache when read from database and when committed into database: this is the default behavior.
See JavaDoc Reference Page...
. It can be changed for a specific EntityManager:

Setting can also be overridden for a specific retrieval operation. For example:

The difference between CacheStoreMode.USE and CacheStoreMode.REFRESH is when bypassing the cache in retrieval operations. In this case, an entity object that is already cached is updated using the fresh retrieved data only when CacheStoreMode.REFRESH is used. This might be useful when the database might be updated by other applications (or using other EntityManagerFactory instances).

Using the Cache Interface

The shared cache is represented by the Cachejavax.persistence.CacheJPA interfaceInterface used to interact with the second-level cache.
See JavaDoc Reference Page...
interface. A Cache instance can be obtained by using the EntityManagerFactoryjavax.persistence.EntityManagerFactoryJPA interfaceInterface used to interact with the entity manager factory for the persistence unit.
See JavaDoc Reference Page...
's getCachegetCache()EntityManagerFactory's methodAccess the cache that is associated with the entity manager factory (the "second level cache").
See JavaDoc Reference Page...
method
:

The Cache object enables checking if a specified entity object is cached:

Cached entity objects can be removed from the cache by one of the evict methods:

  // Remove a specific entity object from the shared cache:
  cache.evictevict(cls, primaryKey)Cache's methodRemove the data for the given entity from the cache.
See JavaDoc Reference Page...
(MyEntity.class, Long.valueOf(id));   // Remove all the instances of a specific class from the cache: cache.evictevict(cls)Cache's methodRemove the data for entities of the specified class (and its subclasses) from the cache.
See JavaDoc Reference Page...
(MyEntity.class);   // Clear the shared cache by removing all the cached entity objects: cache.evictAllevictAll()Cache's methodClear the cache.
See JavaDoc Reference Page...
();

The Cachejavax.persistence.CacheJPA interfaceInterface used to interact with the second-level cache.
See JavaDoc Reference Page...
interface and its methods are unnecessary in most applications.


This documentation explains how to use JPA in the context of the ObjectDB Object Database but mostly relevant
also for ORM JPA implementations, such as Hibernate (and HQL), EclipseLink, TopLink, OpenJPA and DataNucleus.
ObjectDB is not an ORM JPA implementation but an Object Database (ODBMS) for Java with built in JPA 2 support.