Shared (L2) Entity Cache

Every EntityManagerjavax.persistence.EntityManager (JPA Interface)Interface used to interact with the persistence context. 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 newly instantiated entity object.

The scope of the persistence context is one EntityManagerjavax.persistence.EntityManager (JPA Interface)Interface used to interact with the persistence context.. This section describes a level 2  (L2) cache of entity objects, which is managed by the EntityManagerFactoryjavax.persistence.EntityManagerFactory (JPA Interface)Interface used to interact with the entity manager factory for the persistence unit. 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.Cacheable (JPA Annotation)Specifies 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. explicitly. For example:

@Cacheablejavax.persistence.Cacheable (JPA Annotation)Specifies 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. // or @Cacheable(true)
@Entityjavax.persistence.Entity (JPA Annotation)Specifies that the class is an entity.
public class MyCacheableEntityClass {
    ...
}

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.Cacheable (JPA Annotation)Specifies 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. explicitly. For example:

@Cacheablejavax.persistence.Cacheable (JPA Annotation)Specifies 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.(false)
@Entityjavax.persistence.Entity (JPA Annotation)Specifies that the class is an entity.
public class MyNonCacheableEntityClass extends MyCacheableEntityClass {
    ...
}

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.CacheRetrieveMode (JPA Enum)Used 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. enum:

The default setting is USEjavax.persistence.CacheRetrieveMode.USE (JPA Enum Constant)Read entity data from the cache: this is the default behavior.. It can be changed for a specific EntityManager:

  em.setProperty(
      "javax.persistence.cache.retrieveMode", CacheRetrieveModejavax.persistence.CacheRetrieveMode (JPA Enum)Used 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..BYPASSjavax.persistence.CacheRetrieveMode.BYPASS (JPA Enum Constant)Bypass the cache: get data directly from
 the database.);

Setting can also be overridden for a specific retrieval operation:

  // Before executing a query:
  query.setHint("javax.persistence.cache.retrieveMode",
      CacheRetrieveModejavax.persistence.CacheRetrieveMode (JPA Enum)Used 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..BYPASSjavax.persistence.CacheRetrieveMode.BYPASS (JPA Enum Constant)Bypass the cache: get data directly from
 the database.);

  // For retrieval by type and primary key:
  em.find(MyEntity2.class, Long.valueOf(1),
      Collections.<String,Object>singletonMap(
        "javax.persistence.cache.retrieveMode", CacheRetrieveModejavax.persistence.CacheRetrieveMode (JPA Enum)Used 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..BYPASSjavax.persistence.CacheRetrieveMode.BYPASS (JPA Enum Constant)Bypass the cache: get data directly from
 the database.));

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.CacheStoreMode (JPA Enum)Used 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. enum:

The default setting is USEjavax.persistence.CacheStoreMode.USE (JPA Enum Constant)Insert entity data into cache when read from database and insert/update entity data when committed into database: this is the default behavior.. It can be changed for a specific EntityManager:

  em.setProperty("javax.persistence.cache.storeMode", CacheStoreModejavax.persistence.CacheStoreMode (JPA Enum)Used 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..BYPASSjavax.persistence.CacheStoreMode.BYPASS (JPA Enum Constant)Don't insert into cache.);

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

  em.find(MyEntity2.class, Long.valueOf(1),
      Collections.<String,Object>singletonMap(
          "javax.persistence.cache.storeMode", CacheRetrieveModejavax.persistence.CacheRetrieveMode (JPA Enum)Used 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..BYPASSjavax.persistence.CacheStoreMode.BYPASS (JPA Enum Constant)Don't insert into cache.));

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 freshly 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.Cache (JPA Interface)Interface used to interact with the second-level cache. interface. A Cache instance can be obtained by using the EntityManagerFactoryjavax.persistence.EntityManagerFactory (JPA Interface)Interface used to interact with the entity manager factory for the persistence unit.'s getCache method:

  Cachejavax.persistence.Cache (JPA Interface)Interface used to interact with the second-level cache. cache = emf.getCache();

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

  boolean isCached = cache.contains(MyEntity.class, Long.valueOf(id));

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.evict(MyEntity.class, Long.valueOf(id));

  // Remove all the instances of a specific class from the cache:
  cache.evict(MyEntity.class);

  // Clear the shared cache by removing all the cached entity objects:
  cache.evictAll();

The Cachejavax.persistence.Cache (JPA Interface)Interface used to interact with the second-level cache. interface and its methods are unnecessary in most applications.