| Oracle® Coherence Integration Guide for Oracle Coherence Release 3.5 Part Number E14537-01 |
|
|
View PDF |
The Java Persistence API (JPA) is the 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 chapter describes how to configure and use this CacheStore.
Note:
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 works with any JPA-compliant implementation, Oracle recommends using EclipseLink JPA, the Reference Implementation for the JPA 2.0 specification. Oracle is leading the open source EclipseLink project that includes EclipseLink JPA. EclipseLink is available from Eclipse at the following URL:
http://www.eclipse.org/eclipselink
Oracle Toplink includes EclipseLink as its JPA implementation. You can find more information about Toplink and EclipseLink at the following URL:
http://www.oracle.com/technology/products/ias/toplink/index.html
This chapter refers to the following Java classes and interfaces:
Example 1-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" is used generically to refer to both interfaces (the appropriate interface being determined by whether read-only or read-write support is required). Similarly, "JpaCacheStore" refers 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. The JPA run-time 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 provides a high-performance JPA implementation with many advanced features.
Coherence includes a default entity-based CacheStore implementation, JpaCacheStore (and a corresponding CacheLoader implementation, JpaCacheLoader). You can find additional information 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 can be specified in the same way for 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 provider 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 run-time operation.
Example 1-2 is a sample persistence.xml illustrating the typical properties that are set. The transaction type should be set to RESOURCE_LOCAL and the required JDBC properties (eclipselink.jdbc.driver, url, user, and password) 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.
Example 1-2 Sample persistence.xml File for JPA
<persistence xmlns:xsi="http://www.w3.org/2001/XMLSchemainstance" version="1.0" xmlns="http://java.sun.com/xml/ns/persistence"> <persistence-unit name="EmpUnit" transaction-type="RESOURCE_LOCAL"> <provider> org.eclipse.persistence.jpa.PersistenceProvider </provider> <class>com.oracle.coherence.handson.Employee</class> <properties> <property name="eclipselink.jdbc.driver" value="oracle.jdbc.OracleDriver"/> <property name="eclipselink.jdbc.url" value="jdbc:oracle:thin:@localhost:1521:XE"/> <property name="eclipselink.jdbc.user" value="scott"/> <property name="eclipselink.jdbc.password" value="tiger"/> </properties> </persistence-unit> </persistence>
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 entity name of the entity being stored. Unless it is explicitly overridden in JPA it is the unqualified name of the entity class. Example 1-3 uses 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 must be used for each type of persistent entity and Coherence ensures that the name of each cache is set to the name of the entity that is being stored in it.
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 you can 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 various named caches are then directed to use the JPA caching scheme. Example 1-3 is a sample coherence-cache-config.xml which defines a NamedCache named 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 1-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>
When using com.tangosol.coherence.jpa.JpaCacheStore, entities, the persistence unit should be configured to ensure that no changes are made to entities when they are inserted or updated. Any changes made to entities by the JPA provider are not reflected in the Coherence cache and so the entity in the cache will not match the database contents. In particular, entities should not use ID generation, for example, @GeneratedValue, to obtain an ID. IDs should be assigned in application code before an object is put into Coherence. The ID is typically the key under which the entity is stored in Coherence.
Optimistic locking (for example, @Version) should not be used as it may lead to a database transaction commit failure. See "Read-Through, Write-Through, Write-Behind, and Refresh-Ahead Caching" in the Oracle Coherence Getting Started Guide and Sample CacheStores in the Oracle Coherence Developer's Guide for more information on the workings of a CacheStore and how to set up your database schema.
When using either com.tangosol.coherence.jpa.JpaCacheStore or com.tangosol.coherence.jpa.JpaCacheLoader L2 caching should be disabled in your persistence unit. Consult the documentation for your provider. In TopLink, this can be specified on an individual entity with @Cache(shared=false) or as the default in the persistence.xml with the following property:
<property name="eclipselink.cache.shared.default" value="false"/>