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
.
Only resource-local and bootstrapped entity managers are currently supported. Container-managed entity managers and those that use JTA transactions are not currently supported.
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.
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).
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.
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.
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.
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>