Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

EclipseLink/Development/JPA 2.0/cache usaged

< EclipseLink‎ | Development‎ | JPA 2.0
Revision as of 13:10, 14 July 2009 by Guy.pelletier.oracle.com (Talk | contribs) (Used as NamedQuery properties)

JPA 2.0: Cache Usage Settings

JPA 2.0 Root | bug 277039

Discussion

Date Committer(s) Description
Feb 2, 2009 gyorke Initial feature template
June 15, 2009 gpelleti Feature implementation 3.7.1

Summary

The specification introduces cache usage controls in JPA 2.0. Users can use settings on the Entity and Query hints to control how the cache should be used. There are separate settings for how a provider can use the cache for query results and when the cache should be updated with database query results.

Functional Requirements

  • Support specification requirements.
  • Support a cacheable setting on a mapped superclass
  • Default for the "caching element" will be DISABLE_SELECTIVE

Section 3.7.1 - The caching element

Whether the entities and entity-related state of a persistence unit will be cached is determined by the value of the caching element of the persistence.xml file.

The caching element has four possible values: ALL, NONE, ENABLE_SELECTIVE, DISABLE_SELECTIVE.

Caching (persistence.xml) Behavior Code Log
<caching>ALL</caching> Causes all entities and entity related state and data to be cached. None as cache is on by default in EclipsLink Entities marked Cacheable(true) (or its XML equivalent) are ignored and a log warning is issued.
<caching>NONE</caching> Causes caching to be disable for the persistence unit and all cahing is turned off for all entities descriptor.setIsIsolated(true); Entity marked cacheable=false are ignored and a log warning is issued.

The values ENABLE_SELECTIVE and DISABLE_SELECTIVE are used in conjunction with the Cacheable annotation (or XML element). The Cacheable annotation specifies whether an entity should be cached if caching is enabled by the persistence.xml caching element. Cacheable(false) means that the entity and its state must not be cached by the provider. Note: if the user does not specify a caching value, EclipseLink will default to DISABLE_SELECTIVE. This allows them to then turn off the cache by specifying the Cacheable(false) and not having to modify their persistence.xml.

// From JPA 2.0 Specification
@Target({TYPE}) @Retention(RUNTIME)
public @interface Cacheable {
  boolean value() default true;
}
Caching (persistence.xml) Behavior Code Log
<caching>ENABLE_SELECTIVE</caching> Enables the cache and causes entities for which Cacheable(true) (or its XML equivalent) is specified to be cached. Entities for which Cacheable(true) is not specified or for which Cacheable(false) is specified must not be cached. True (or no setting) - nothing, cache is on by default, False - descriptor.setIsIsolated(true); None.
<caching>DISABLE_SELECTIVE</caching> Enables the cache and causes all entities to be cached except those for which Cacheable(false) is specified. Entities for which Cacheable(false) is specified must not be cached. True (or no setting) - nothing as cache is on by default. False, descriptor.setIsIsolated(true); None

EclipseLink will also go one step further and allow users to configure the Cacheable setting on a mapped superclass. The logic of this is similar to specifying an exclude-superclass-listener setting on a mapped superclass. To use this feature, the user can either specify annotations directly or use the eclipselink-orm schema. Note: a cacheable setting within an inheritance hierarchy will only be supported on the root of the hierarchy.

@MappedSuperclass
@Cacheable(true)
public class CacheableTrueMappedSuperclass {
    private int id;
    
    public CacheableTrueMappedSuperclass() {}
    
    @Id
    @GeneratedValue(strategy=TABLE, generator="CACHEABLE_TABLE_GENERATOR")
    public int getId() {
        return id;
    }
    
    public void setId(int id) {
        this.id = id;
    }
}

@Entity(name="JPA_SUB_CACHEABLE_FALSE")
@Cacheable(false)
public class SubCacheableFalseEntity extends CacheableTrueMappedSuperclass {
    public SubCacheableFalseEntity() {}
}

@Entity(name="JPA_SUB_CACHEABLE_NONE")
// Will pick up the Cacheable(true) setting from the mapped superclass.
public class SubCacheableNoneEntity extends CacheableTrueMappedSuperclass {
    public SubCacheableNoneEntity() {}
}

// These classes mapped in XML would look as follows:

<table-generator name="CACHEABLE_TABLE_GENERATOR" table="CACHEABLE_SEQ" pk-column-name="SEQ_NAME" value-column-name="SEQ_COUNT" pk-column-value="CACHEABLE_SEQ"/>
<mapped-superclass class="CacheableTrueMappedSuperclass" access="FIELD" cacheable="true">
  <attributes>
    <id name="id">
      <generated-value strategy="TABLE" generator="CACHEABLE_TABLE_GENERATOR"/>
    </id>
  </attributes>
</mapped-superclass>
<entity name="SUB_CACHEABLE_FALSE" class="SubCacheableFalseEntity" access="FIELD" cacheable="false"/>
<!-- Will pick up the Cacheable(true) setting from the mapped superclass. -->
<entity name="SUB_CACHEABLE_NONE" class="SubCacheableNoneEntity" access="FIELD"/>

Section 3.7.2 - Cache mode properties

// From JPA 2.0 Specification
public enum CacheRetrieveMode {
 
    /**
     * Read entity data from the cache: this is
     * the default behavior.
     */
    USE,
 
    /**
     * Bypass the cache: get data directly from
     * the database.
     */
    BYPASS
}
 
public enum CacheStoreMode {
 
    /**
     * Insert/update entity data into cache when read
     * from database and when committed into database:
     * this is the default behavior. Does not force refresh
     * of already cached items when reading from database.
     */
    USE,
 
    /**
     * Don't insert into cache.
     */
    BYPASS,
 
    /**
     * Insert/update entity data into cache when read
     * from database and when committed into database:
     * Forces refresh of cache for items read from database.
     */
    REFRESH
}

Most of this support should already exist at the query level but entity level settings may need to be added. PersistenceUnitInfo class updates. orm.xml and persistence.xml processing and annotation processing will be required

Used as EntityManager properties

Cache mode properties may be specified at the level of the persistence context by means of the Entity Manager setProperties method and may also be specified for the EntityManager find and refresh methods. Cache mode properties specified for the find, refresh and override those specified for the persistence context for the specified find and refresh invocations.

Note: The existing EclipseLink property "eclipselink.cache-usage" will override any JPA cacheRetrieveMode and/or cacheStoreMode properties specified. Both can not be used in conjunction with one another.

// To set individual properties (to overwrite existing or set new ones):
em.setProperty(QueryHints.CACHE_RETRIEVE_MODE, CacheRetrieveMode.USE);
em.setProperty(QueryHints.CACHE_STORE_MODE, CacheRetrieveMode.BYPASS);

// Or to overwrite the existing properties as a whole:
HashMap properties = new HashMap();
properties.put(QueryHints.CACHE_RETRIEVE_MODE, CacheRetrieveMode.USE);
properties.put(QueryHints.CACHE_STORE_MODE, CacheStoreMode.BYPASS);
em.setProperties(properties);

// EntityManager find operation (will use the value from the cache):
em.find(MyEntity.class, id);

// EntityManager find operation with properties (will read the entity from the DB and update the cache)
HashMap findProperties = new HashMap();
findProperties.put(QueryHints.CACHE_RETRIEVE_MODE, CacheRetrieveMode.BYPASS);
findProperties.put(QueryHints.CACHE_STORE_MODE, CacheStoreMode.USE);
em.find(MyEntity.class, id, findProperties);

Used as NamedQuery properties

Cache mode properties specified at the level of the persistence context by means of the Entity Manager are also used within the execution of queries. The queries themselves may override those settings through their own setProperties method or by the query definition itself (if defined in annotations or XML)


// Entity manager property settings:
em.setProperty(QueryHints.CACHE_RETRIEVE_MODE, CacheRetrieveMode.USE);
em.setProperty(QueryHints.CACHE_STORE_MODE, CacheRetrieveMode.BYPASS);


// A named query definition that will override the Entity Manager properties completely
// and use a retrieve mode of BYPASS and a store mode of USE.
@NamedQuery(
  name="findMyEntityByPK",
  query="SELECT OBJECT(e) FROM MYENTITY e WHERE e.id = :id",
  hints={
    @QueryHint(name=QueryHints.CACHE_RETRIEVE_MODE, value="BYPASS"),
    @QueryHint(name=QueryHints.CACHE_STORE_MODE, value="USE")
  }
)


// A named query definition that will override part of the EntityManager properties and will
// used a retrieve mode of BYPASS and a store mode of BYPASS (as specified by the EM)
@NamedQuery(
  name="findMyEntityByPK",
  query="SELECT OBJECT(e) FROM MYENTITY e WHERE e.id = :id",
  hints={
    @QueryHint(name=QueryHints.CACHE_RETRIEVE_MODE, value="BYPASS"),
  }
)

Design

Metadata processing will need to be expanded to include processing of the Cacheable annotation and the <cacheable> element from XML. Internal this will reuired changes to EntityAccessor. Since an EntityAccessor extends MappedSuperclassAccessor, it is fairly straight forward to expand this functionality to mapped superclasses.

Documentation

JPA Specification sections: 3.7, 3.7.1, 3.7.2, 11.1.7

Testing

New testing models using annotations and XML will be created.

Work Estimate

  1. Develop model for testing cache usage settings
    approx 3 days
  2. Update processing
    approx 3 days
  3. Implement Functionality
    approx 3 days

Back to the top