Notes on JPA L2 Caching

Here are some notes on L2 (level 2/shared) cache in JPA

Quick facts

  • JPA L2 cache was standardized in JPA 2.0 (Java EE 6)
  • Based on EntityManagerFactory i.e. its a global cache common across all Persistence Units
  • A layer which site between the L1 cache (EM) and the database i.e. the database is queried only if the entity is not in the L1 cache and L2 cache
  • This feature is optional (but most of the well known providers support it)

Initial setup

@Cacheable: this annotation is used to declaratively configure L2 (shared) caching for a JPA entity

Cache Modes

Specified in persistence.xml or during Entity Manager Factory creation (programmatic)

  • NOT_SPECIFIEDdefault mode. Provider specific behavior (e.g. Eclipselink uses L2 cache by default vs Hibernate which needs explicit configuration for the same)
  • ENABLE_SELECTIVE – only entity classes with @Cacheable(true) are cached
  • DISABLE_SELECTIVE – entity classes with @Cacheable(false) are not cached
  • ALL – all the JPA entities are cached
  • NONE – none of the entities are cached

A JPA persistence.xml demonstrating usage of L2 caching config parameter

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="" xmlns:xsi="" xsi:schemaLocation="">
<persistence-unit name="jap-punitxml-testPU" transaction-type="JTA">
<property name="javax.persistence.query.timeout" value="3000"/>
<property name="javax.persistence.lock.timeout" value="2000"/>

view raw


hosted with ❤ by GitHub

Here is a simple JPA entity with explicit L2 caching metadata

public class Employee {
//rest of the code…

view raw

hosted with ❤ by GitHub

Override mode

In addition to the basic configuration options specified above, JPA allows you to dynamically specify how you want to interact with the L2 cache. These options are available for the entities which have been explicitly configured to participate in L2 caching

They can be enforced using the following methods

  • Entity Manager property
  • find method of Entity Manager
  • hint during query execution

Read options

These options come into play during reading/fetching data from the cache and can be specified using the javax.persistence.cache.retrieveMode property

  • CacheRetrieveMode.USE: read from L2 cache
  • CacheRetrieveMode.BYPASS: skip the cache (refer the database directly)

Indicate L2 cache usage via EM property

public class EmployeeManager{
EntityManager em;
public Employee getByID(String id){
em.setProperty("javax.persistence.cache.retrieveMode", CacheRetrieveMode.USE); //look for the employee in the L2 cache first
return em.find(Employee.class, id);

Write options

These options are used to configure operations related to putting data into the cache and can be specified using the javax.persistence.cache.storeMode property

  • CacheStoreMode.USE: populate the cache in response to the executed operation
  • CacheStoreMode.BYPASS: do not modify the cache contents post operation
  • CacheStoreMode.RERESH: to be used when your database is affected by external sources other than your application itself. Using this option forces the JPA provider to skip the cache (during fetch), go to the database and populate the result into the cache (effectively, a refresh operation)

NoteCacheRetrieveMode and CacheStoreMode are enums

Explicit L2 cache overrides using EM and query hints

public class YetAnotherEmployeeManager {
EntityManager em;
public Employee getByPrimaryKey(String employeeID){
Map<String,Object> searchProp = new HashMap<>();
searchProp.put("javax.persistence.cache.storeMode", CacheStoreMode.BYPASS); //don't put the employee into the L2 cache
return em.find(Employee.class, employeeID);
public Employee getByOrganization(String orgID){
TypedQuery<Employee> query = em.createQuery("SELECT e FROM Employees e WHERE e.orgID = :orgId", Employee.class);
query.setHint("javax.persistence.cache.storeMode", CacheRetrieveMode.REFRESH);
query.setParameter("orgId", orgId);
return query.getSingleResult();

Other stuff . . .

Other L2 cache related methods exposed by the javax.persistence.Cache interface (these are self explanatory)

  • contains: is this entity in the L2 cache ?
  • evict: remove this entity from the cache
  • evictAll: clear the shared cache

Interrogating the JPA L2 cache

public class JPACacheOps{
EntityManager em;
public void testL2Cache(String id){
String id = "007";
String anotherID = "42";
em.find(Employee.class, id);
em.find(Employee.class, id);
//both '007' and '42' are in L2 cache
String orgID = "org123";
em.find(Org.class, orgID); //'org123' is now in L2 cache
Cache sharedL2Cache = em.getEntityManagerFactory().getCache();
sharedL2Cache.contains(Employee.class , id); //returns true
sharedL2Cache.evict(Employee.class, id); //'007' removed from shared cache
sharedL2Cache.contains(Employee.class, id); //returns false
sharedL2Cache.evict(Employee.class); //ALL 'Employee' entities removed
sharedL2Cache.contains(Employee.class, anotherID); //returns false
sharedL2Cache.contains(Org.class , orgID); //returns true
sharedL2Cache.evictAll(); //ALL entities removed
sharedL2Cache.contains(Ord.class, orgID); //returns false



About Abhishek

Loves Go, NoSQL DBs and messaging systems
This entry was posted in Java EE and tagged , , , , . Bookmark the permalink.

6 Responses to Notes on JPA L2 Caching

  1. Pingback: Java Weekly 22/16: JDBC insert, L2 caching, eager optimization

  2. Rycho says:

    I had problems when using JPA+cache on glassfish. A simplest case of using JPA, one might say:
    – load an entity
    – modify it (using its setters)
    – abort transaction (throw an exception)
    The problem was that I was modifying a shared object and other transactions could see the change although it was not committed.


  3. Arun Menon says:

    Thanks !!! Definitely Helpful


  4. david says:

    Very informative. Do you have any example of a cache’d Entity containing an collection?


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s