+

Search Tips   |   Advanced Search

Configure OpenJPA caching to improve performance

The OpenJPA implementation gives you the option of storing frequently used data in the memory to improve performance. OpenJPA provides concurrent data and concurrent query caches that support applications to save persistent object data and query results in memory to share among threads and for use in future queries.

The OpenJPA data cache is a cache of persistent object data that operates at the EntityManagerFactory level. This optional-use cache is designed to increase performance while remaining in full compliance with the Java Persistence API (JPA) standard. This means that enabling the caching option can increase the performance of the application, with no changes to your code. The OpenJPA data cache is designed to provide significant performance increases over cacheless operations and ensures that behavior is identical in both cache-enabled and cacheless operations.

When enabled, the cache is examined before accessing the data store. The cache stores data when objects are committed and when persistent objects are loaded from the data store. If operating in a single JVM environment, the JVM maintains and shares a data cache across all EntityManager instances obtained from a particular EntityManagerFactory. The OpenJPA data cache cannot do this in a distributed environment because caches in different JVMs, created from different EntityManagerFactory objects are not synchronized.

Using the OpenJPA cache in a multi-JVM environment can be done by configuring the OpenJPA second level (L2) cache provider plug-in.

Configuring the DynaCache plug-in allows for the Data and Query cache content to be replicated and consistent across JVMs. Other alternatives include setting up an event notification framework or using a third-party distributed cache such as WebSphere eXtreme Scale.

We can enable the OpenJPA data cache for a single or a multiple JVM environment, set its default element size, including soft references, and specify timeout values.

To set up and configure the OpenJPA data cache, do the following:

  1. To enable the cache for a single JVM...

      <property name="openjpa.DataCache" value="true"/> <property name="openjpa.RemoteCommitProvider" value="sjvm"/>

    To enable the data cache in a distributed environment, the configure openjpa.RemoteCommitProvider specifically for the environment, or a third-party cache management utility can be used.

  2. The maximum cache size can be adjusted by setting the CacheSize property:

      <property name="openjpa.DataCache" value="true(CacheSize=5000...

    By default, the OpenJPA data cache holds 1000 elements. Objects that are pinned into the cache are not counted when determining if the cache size exceeds its maximum size. If the cache overflows, it evicts random elements. We can preserve evicted elements longer with the SoftReferenceSize property. By default, soft references are unlimited. If we must, we can limit the number of soft references or set to 0 to disable soft references completely:

      <property name="openjpa.DataCache" value="true(CacheSize=5000 SoftReferenceSize=0 ...

  3. We can specify that a cache is cleared at certain times. The EvictionSchedule property of the OpenJPA cache implementation accepts a cron style eviction schedule. The cron format specifies the minute, hour of day, day of month, day of month, and day of the week beginning with 1 for Sunday; the * symbol (asterisk), indicates match all. To schedule a cache to evict at 45 minutes past 3 PM on Sunday every month you would add this property:

      <property name="openjpa.DataCache" value="true(CacheSize=5000 SoftReferenceSize=0 EvictionSchedule='15,45 * * 1'")/>

  4. To specify a cache timeout value for a single class, set the timeout metadata extension to the amount of time in milliseconds that the data of the class is valid; for example:

      @Entity
      @DataCache(timeout=10000)
      public class Employee {
          ...
      }

After configuring the data cache, we can use it after you restart the application.

Refreshing an entity may lead to different behavior with or without a DataCache when a separate process or part of the same application are updated or even deleted the corresponding record in the database. By default, entities are refreshed from the database even when DataCache is active. Therefore, with the default configuration the refresh behaves identically with or without a DataCache.

However, a persistence unit can be configured to refresh entities from DataCache with the property openjpa.RefreshFromDataCache for improved performance. Under this configuration, any out-of-band changes that occur in the database record do not appear in the refreshed state of the entity.

Regardless of the openjpa.RefreshFromDataCache setting, the DataCache is always bypassed for refresh when locks are active, such as for a pessimistic transaction, in a persistence context. An application may activate openjpa.RefreshFromDataCache but can still bypass the DataCache while refreshing an entity by explicitly evicting the entity from DataCache before refresh.

OpenJPA provides a concurrent query cache that supports applications to save persistent object data and query results in memory to share among threads and for use in future queries. The query cache stores the object IDs returned by query executions. When you run a query, OpenJPA assembles a key based on the query properties and the parameters used at execution time, and checks for a cached query result. If one is found, the object IDs in the cached result are looked up, and the resultant persistence-capable objects are returned. Otherwise, the query is executed against the database, and the object IDs loaded by the query are put into the cache.

We can configure the query cache settings in a similar way to the data cache. The interface provided to the query cache is the org.apache.openjpa.persistence.QueryResultCache class. We can access this class through the OpenJPAEntityManagerFactory.

The default query cache implementation caches 100 query executions in a least-recently-used cache. This can be changed by setting the cache size in the CacheSize plug-in property. Like the data cache, the query cache also has a backing soft reference map that can be changed using the SoftReferenceSize property. To keep queries in the cache at all times, we can pin them to a cache. To change the query cache properties do the following:

  1. Modify the CacheSize property of the openjpa.QueryCache:

      <property name="openjpa.QueryCache" value="true("CacheSize=1000, ...

  2. Change the SoftReferenceSize property to enable and control the size of this map:

      <property name="openjpa.QueryCache" value="true(CacheSize=1000, SoftReferenceSize=100")/>

    The SoftReferenceSize table is disabled by default. Setting the size enables it.

  3. Pin or unpin queries in the cache through the QueryResultCache with this syntax:

      public void pin(Query q);
      public void unpin(Query q);

Modifying these properties allows us to make better use of the query cache.

OpenJPA provides classes that may be extended for further functionality.

OpenJPA provides a cache that provides caching of SQL strings used by find operations performed on the entity manager and some queries to manage eagerly fetched relationships. When this cache is enabled, SQL queries used by these operations are generated one time per entity manager factory and can be reused. This cache is enabled by default but can also be configured through the openjpa.jdbc.QuerySQLCache configuration property.

The query SQL cache can be configured or disabled through the openjpa.jdbc.QuerySQLCache property. By default, this property is set to true. When the property is set to true, the cache is enabled and uses the org.apache.openjpa.util.CacheMap class for its cache store. The CacheMap is a managed cache, meaning that it limits the number of cache entries and has a cache eviction scheme to manage memory usage. If the cache is set to all the org.apache.openjpa.lib.util.ConcurrentHashMap class is used as a cache store. The ConcurrentHashMap is not a managed cache so entries remain in the cache for the lifetime of an entity manager factory. This caching mechanism can provide better performance at the expense of increased memory usage. A custom cache store class can also be specified if it implements the java.util.Map interface. To disable the cache, specify the value false. See the following examples on how to configure or disable the SQL query cache:


What to do next

We can read more about Caching in the OpenJPA for all caching extensions in the Apache OpenJPA User Guide.


Related tasks

Develop JPA 2.x applications for a Java SE environment
  • Dynamic cache provider for the JPA 2.0 second level cache
    Apache OpenJPA User Guide
    Apache OpenJPA User Guide: Cache Configuration