27 Configuring Coherence for JPA

The Java Persistence API (JPA) is the primary standard for Object-Relational mapping (ORM) and enterprise Java persistence. Several open source and commercial implementations exist and are being developed.

Coherence ships a CacheStore implementation that uses JPA to load and store objects to the database. This document describes how to configure and use this CacheStore.

27.1 Limitations

Only resource-local and bootstrapped entity managers are currently supported. Container-managed entity managers and those that use JTA transactions are not currently supported.

27.2 Obtaining a JPA Implementation

A JPA provider is not shipped with Coherence, but is easy to obtain. Although the JPA CacheStore will work with any compliant JPA implementation, we recommend using one of the following:

  • TopLink Essentials is the Reference Implementation for the JPA 1.0 specification. It is open source and free, available from the Oracle Technology Network (OTN) at http://otn.oracle.com/jpa.

  • Eclipse JPA will be the Reference Implementation for the forthcoming JPA 2.0 specification. Oracle is leading the open source EclipseLink project that includes Eclipse JPA. EclipseLink is available from Eclipse at http://www.eclipse.org/eclipselink.

27.3 Conventions

This document refers to the following Java classes and interfaces:

Example 27-1 JPA-related Classes and Interfaces

com.tangosol.coherence.jpa.JpaCacheLoader
com.tangosol.coherence.jpa.JpaCacheStore

com.tangosol.net.NamedCache (extends java.util.Map)

com.tangosol.net.cache.CacheLoader
com.tangosol.net.cache.CacheStore

As the CacheStore interface extends CacheLoader, the term "CacheStore" will be used generically to refer to both interfaces (the appropriate interface being determined by whether read-only or read-write support is required). Similarly, "JpaCacheStore" will refer to both implementations.

The Coherence cache configuration file is referred to as the coherence-cache-config.xml (the default name). The JPA persistence implementation is referred to simply as the JPA provider or JPA vendor. The JPA runtime configuration file is referred to as the persistence.xml, and the JPA Object-Relational mapping file is referred to as the orm.xml (the default name).

27.4 Using the Coherence JpaCacheStore

The JPA is a standard API for mapping, querying and storing Java objects to a database. The characteristics of the different JPA implementations may differ, however, when it comes to caching, threading, and overall performance. TopLink Essentials is a high-performing JPA implementation that meets the performance needs of most applications.

Coherence includes a default entity-based CacheStore implementation, JpaCacheStore (and a corresponding CacheLoader implementation, JpaCacheLoader). Other information may be found in the Javadoc for the implementing classes.

27.4.1 Mapping the Persistent Classes

The first step in being able to load and store objects through the CacheStore is to ensure that the classes are mapped to the database. JPA mappings are standard, and hence may be specified the same way for any and all JPA providers.

Entities may be mapped either by annotating the entity classes or by adding an orm.xml or other XML mapping file. See the JPA vendor documentation for more on how to map JPA entities.

27.4.2 Configuring JPA

A typical JPA configuration involves making changes to the persistence.xml file. Within the persistence.xml are the properties that dictate runtime operation. Example 27-2 is a sample persistence.xml showing the typical properties that are set.

Example 27-2 Sample persistence.xml File for JPA

<persistence xmlns="http://java.sun.com/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
        http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
    version="1.0">

   <persistence-unit name="EmpUnit" transaction-type="RESOURCE_LOCAL">

     <provider>oracle.toplink.essentials.PersistenceProvider</provider>

     <class>com.acme.Employee</class>

     <properties>
       <property name="toplink.jdbc.driver" value="oracle.jdbc.OracleDriver"/>
       <property name="toplink.jdbc.url" value="jdbc:oracle:thin:@localhost:1521:XE"/>
       <property name="toplink.jdbc.user" value="scott"/>
       <property name="toplink.jdbc.password" value="tiger"/>
     </properties>

   </persistence-unit>

</persistence>

The transaction type should be set to RESOURCE_LOCAL and the four JDBC properties should contain the appropriate values for connecting and logging into your database. Classes that are mapped using JPA annotations should be listed in <class> elements.

27.4.3 Configuring Coherence

A coherence-cache-config.xml must be specified to override the default Coherence settings and define the JpaCacheStore caching scheme. The caching scheme should include a <cachestore-scheme> element that lists the JpaCacheStore class and includes three parameters.

  • The first parameter is the entity name of the entity being stored. Unless it is explicitly overridden in JPA it will be the unqualified name of the entity class. In Example 27-3, we make use of the built-in Coherence macro {cache-name} that translates to the name of the cache that is constructing and using the CacheStore. This works because a separate cache should be used for each type of persistent entity and we will ensure that the name of each cache will be set to the name of the entity that is being stored in it.

  • The second parameter is the fully qualified name of the entity class. If the classes are all in the same package and use the default JPA entity names then we can once again use the {cache-name} macro to fill in the part that is variable across the different entity types. In this way the same caching scheme can be used for all of the entities that are cached within the same persistence unit.

  • The third parameter is the persistence unit name, which should be the same as the name specified in the persistence.xml.

The various named caches are then directed to use the JPA caching scheme. Example 27-3 is a sample coherence-cache-config.xml used to define a NamedCache called "Employee" that caches instances of the Employee class. To define additional entity caches for more classes then more <cache-mapping> elements may be added.

Example 27-3 Assigning Named Caches to a JPA Caching Scheme

<cache-config>

  <caching-scheme-mapping>

    <cache-mapping>
      <!-- Set the name of the cache to be the entity name  -->
      <cache-name>Employee</cache-name>
      <!-- Configure this cache to use the scheme defined below  -->
      <scheme-name>jpa-distributed</scheme-name>
    </cache-mapping>

  </caching-scheme-mapping>

  <caching-schemes>

    <distributed-scheme>

      <scheme-name>jpa-distributed</scheme-name>
      <service-name>JpaDistributedCache</service-name>

      <backing-map-scheme>
        <read-write-backing-map-scheme>

          <internal-cache-scheme>
            <local-scheme/>
          </internal-cache-scheme>

          <!- Define the cache scheme -->
          <cachestore-scheme>
            <class-scheme>
              <class-name>
                com.tangosol.coherence.jpa.JpaCacheStore
              </class-name>
              <init-params>

                <!-- This param is the entity name -->
                <init-param>
                  <param-type>java.lang.String</param-type>
                  <param-value>{cache-name}</param-value>
                </init-param>

                <!-- This param is the fully qualified entity class -->
                <init-param>
                  <param-type>java.lang.String</param-type>
                  <param-value>com.acme.{cache-name}</param-value>
                </init-param>

                <!-- This param should match the value of the -->
                <!-- persistence unit name in persistence.xml -->
                <init-param>
                  <param-type>java.lang.String</param-type>
                  <param-value>EmpUnit</param-value>
                </init-param>

              </init-params>
            </class-scheme>
          </cachestore-scheme>

        </read-write-backing-map-scheme>
      </backing-map-scheme>

    </distributed-scheme>

  </caching-schemes>

</cache-config>