Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Notes on JPA L2 Caching

DZone's Guide to

Notes on JPA L2 Caching

Take a look here at some JPA L2 cache quick facts and example code.

· Java Zone
Free Resource

Download Microservices for Java Developers: A hands-on introduction to frameworks and containers. Brought to you in partnership with Red Hat.

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="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
  <persistence-unit name="jap-punitxml-testPU" transaction-type="JTA">
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
    ...............
    <shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
    <properties>
      <property name="javax.persistence.query.timeout" value="3000"/>
      <property name="javax.persistence.lock.timeout" value="2000"/>
    </properties>
    ...............
  </persistence-unit>
</persistence>

Here is a simple JPA entity with explicit L2 caching metadata:

@Entity
@Table("EMPLOYEES")
@Cacheable(true)
public class Employee {
  //rest of the code...
}

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.

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.REFRESH: 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)

Note: CacheRetrieveMode and CacheStoreMode are enums

Explicit L2 cache overrides using EM and query hints

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:

@Stateless
public class JPACacheOps{
  @persistenceContext("emp_PU")
  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
  }
}

Cheers!

Download Building Reactive Microservices in Java: Asynchronous and Event-Based Application Design. Brought to you in partnership with Red Hat

Topics:
annotation ,cache ,cacheable ,configuration ,entities ,jpa ,basic ,caching ,entity

Published at DZone with permission of Abhishek Gupta, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}