Show TOC

Caches in the JPA ImplementationLocate this document in the navigation structure

Use

Introduction to JPA Caches

An application that uses JPA reads an entity either explicitly (by executing a find or a query) or implicitly (by navigating to a related entity). To guarantee referential consistency, JPA first tries to locate an entity in the persistence context associated with the entity manager. Only if an entity is not found in the persistence context does JPA retrieve its persistent state from the database. Therefore, the persistence context is also referred to as a “first level cache” .

However, when the persistence context is closed, it is cleared. In the case of a transaction-scoped persistence context, this happens at the end of the transaction.

Many applications use entities that are frequently read but rarely changed. To avoid accessing the database each time such entities are read in a new persistence context, a server-side caching mechanism is necessary to outlast the persistence context. This is the “second level cache” .

Cacheable Entities

Entities which are rarely changed can be declared as cacheable within the entity cache. To do this, you use the @Cacheable annotation on the entity class.

Sample Code
                  import com.sap.jpa.Cacheable;

@Entity
@Cacheable
public class Country {
        @Id
        String name;
        String headOfState;
}
               

Alternatively, cacheable entities can be specified using the com.sap.jpa.cache.cacheable-classes property in the persistence.xml .

For more information, see persistence.xml .

Cacheable entities can have relationships with other entities. For single-valued relationships, the value of the relationship (that is, the ID of the related entity) is also cached. For collection-valued relationships, the value of the relationship (that is, the IDs of the related entities) are not cached. This means that the collection-valued relationships are established upon retrieval of the cached entity from the cache. For lazily loaded collection-valued relationships (the default), a lazily loadable collection is created without accessing the database. For eagerly loaded collection-valued relationships ( FetchType.EAGER ), the database must be accessed.

Read-Only Entities

A “read-only entity” is an entity that is never changed by the application during its entire life cycle, that is, the application only inserts or reads entities of this class, but never changes or deletes these entities.

The SAP implementation of JPA allows selected entities to be declared as read-only using the readOnly attribute of the @Cacheable annotation.

Sample Code
                  import com.sap.jpa.Cacheable;

@Entity
@Cacheable(readOnly=true)
        public class Continent {
        @Id
        String name;
}
               

Alternatively, read-only entities can be specified using the com.sap.jpa.cache.read-only-classes property in the persistence.xml .

For more information, see persistence.xml .

Read-only entities are also considered to be cacheable.

Working with read-only entities has the following specifics:

  • The SAP implementation of JPA is not required to perform change tracking on read-only entities. If an application changes a read-only entity, the behavior is undefined.

  • Read-only entities must not be part of an inheritance hierarchy.

Read-only entities cannot have relationships with non-read-only entities.

Types of Caches in the JPA Implementation

Entity Cache

For second-level caching on the object layer, the SAP implementation of JPA provides an “entity cache” . It caches entities that are explicitly declared to be cacheable. Upon retrieval of a cacheable entity, the JPA runtime first looks for this entity in the persistence context, then in the entity cache, and finally in the database.

Unless an entity is declared as read-only, the entity cache returns a copy of the cached entity. If the entity declared as read-only, a reference to the shared instance, which is stored in the cache, is returned.

Table Buffer

If you are running JPA on the Open SQL layer, second level caching can alternatively be achieved using the table buffer to cache database table rows.

For more information, see:

Running JPA Applications on the System Data Source

Table Buffer

Query Result Cache

The “query result cache” stores the result sets of JPQL queries or native queries. To hit the cache, a query must be executed subsequently with the same query text, the same parameter values, and the same hints.

By default, no queries are cached. To indicate that a certain query is to be cached, you must set the com.sap.jpa.cache.query-result hint with the value cached on this query.

Sample Code
                  @NamedQuery(name="getMostPopularBooks", query="select b from book order by b.popularity desc", hints= {
        @QueryHint(name = "com.sap.jpa.cache.query-result",
        value = "cached") })
@Cacheable
@Entity
public class Book {
        @Id
        int id;
        String author;
        String title;
        int popularity;
}
               

The query result cache stores only the primary keys of the entities contained in the result set. Therefore, the query result cache must always be used together with the entity cache or with the table buffer.

Note

SAP Compliance Switch

The query result cache cannot be used by applications that declare compliance with the SAP Product Standard.

To declare SAP Product Standard compliance, the SAP implementation of JPA uses the com.sap.jpa.compliance.sap-product-standard property in the persistence.xml .

More information: persistence.xml

For more information about the SAP Product Standard compliance, refer to SAP Note 1169694.

Working with JPA Caches

Stale Reads and timeToLive

When a cached entity is updated or deleted, it is invalidated in the entity cache of the cluster node where the operation occurs. However, the invalidation is not propagated to other cluster nodes. Hence, on a different cluster node a stale read may occur - an entity can be read from the cache in a state that does not reflect the state in the database.

By default, entities stay in the entity cache indefinitely, unless they are invalidated by an update or a delete operation. To control the maximum staleness of an entity, you can specify the time-to-live of an entity in the cache using the timeToLive attribute of the @Cacheable annotation. The value of this attribute is the number of seconds after which the entity is no longer read from the cache, but reread from the database.

Sample Code
                  import com.sap.jpa.Cacheable;

@Entity
@Cacheable(timeToLive=30)
public class Match {
        @Id
        int matchId;
        int goalsOfHomeTeam;
        int goalsOfGuestTeam;
}

               

Cache Size and Displacement

The entity cache and the query result cache have default maximum sizes of 100,000 and 10,000 entries, respectively. If the limits are reached, randomly chosen entries are displaced.

You can configure the maximum size of the entity cache and the query result cache using the com.sap.jpa.cache.object-cache.size and the com.sap.jpa.cache.query-result-cache.size properties in the persistence.xml , respectively

Note
  • To avoid reading old data, the query result cache does not return data that is older than 20 minutes. Upon request, the relevant data is reread from the database instead. This timeout is not currently configurable.

  • The JPA caches can be configured and monitored via the JPA Monitors tool in the SAP NetWeaver Administrator.

    For more information, see Using JPA Monitors .