mirror of https://github.com/apache/openjpa.git
1849 lines
76 KiB
XML
1849 lines
76 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!--
|
|
Licensed to the Apache Software Foundation (ASF) under one
|
|
or more contributor license agreements. See the NOTICE file
|
|
distributed with this work for additional information
|
|
regarding copyright ownership. The ASF licenses this file
|
|
to you under the Apache License, Version 2.0 (the
|
|
"License"); you may not use this file except in compliance
|
|
with the License. You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing,
|
|
software distributed under the License is distributed on an
|
|
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
KIND, either express or implied. See the License for the
|
|
specific language governing permissions and limitations
|
|
under the License.
|
|
-->
|
|
<chapter id="ref_guide_runtime">
|
|
<title>
|
|
Runtime Extensions
|
|
</title>
|
|
<para>
|
|
This chapter describes OpenJPA extensions to the standard JPA
|
|
interfaces, and outlines some additional features of the OpenJPA runtime.
|
|
</para>
|
|
<section id="ref_guide_runtime_arch">
|
|
<title>
|
|
Architecture
|
|
</title>
|
|
<para>
|
|
Internally, OpenJPA does not adhere to any persistence specification. The
|
|
OpenJPA kernel has its own set of APIs and components. Specifications like JPA
|
|
and JDO are simply different "personalities" that OpenJPA's native kernel
|
|
can adopt.
|
|
</para>
|
|
<para>
|
|
As an OpenJPA user, you will not normally see beneath
|
|
OpenJPA's JPA personality. OpenJPA allows you to access its feature set without
|
|
leaving the comfort of JPA. Where OpenJPA goes beyond standard JPA
|
|
functionality, we have crafted JPA-specific APIs to each OpenJPA extension for
|
|
as seamless an experience as possible.
|
|
</para>
|
|
<para>
|
|
When writing OpenJPA plugins or otherwise extending the OpenJPA runtime,
|
|
however, you will use OpenJPA's native APIs. So that you won't feel lost, the
|
|
list below associates each specification interface with its backing native
|
|
OpenJPA component:
|
|
</para>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>
|
|
<classname>javax.persistence.EntityManagerFactory</classname>: <emphasis>
|
|
<classname>org.apache.openjpa.kernel.BrokerFactory</classname></emphasis>
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<classname>javax.persistence.EntityManager</classname>: <emphasis><classname>
|
|
org.apache.openjpa.kernel.Broker</classname></emphasis>
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<classname>javax.persistence.Query</classname>: <emphasis><classname>
|
|
org.apache.openjpa.kernel.Query</classname></emphasis>
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<classname>org.apache.openjpa.persistence.Extent</classname>: <emphasis>
|
|
<classname>org.apache.openjpa.kernel.Extent</classname></emphasis>
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<classname>org.apache.openjpa.persistence.StoreCache</classname>: <emphasis>
|
|
<classname>org.apache.openjpa.datacache.DataCache</classname></emphasis>
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<classname>org.apache.openjpa.persistence.QueryResultCache</classname>:
|
|
<emphasis><classname>org.apache.openjpa.datacache.QueryCache</classname>
|
|
</emphasis>
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<classname>org.apache.openjpa.persistence.FetchPlan</classname>: <emphasis>
|
|
<classname>org.apache.openjpa.kernel.FetchConfiguration</classname></emphasis>
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<classname>org.apache.openjpa.persistence.Generator</classname>: <emphasis>
|
|
<classname>org.apache.openjpa.kernel.Seq</classname></emphasis>
|
|
</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
<para>
|
|
The <link linkend="ref_guide_runtime_openjpapersistence"><classname>
|
|
org.apache.openjpa.persistence.OpenJPAPersistence</classname></link> helper
|
|
allows you to convert between <classname>EntityManagerFactories</classname> and
|
|
<classname>BrokerFactories</classname>, <classname>EntityManager</classname>s
|
|
and <classname>Broker</classname>s.
|
|
</para>
|
|
<section id="ref_guide_runtime_broker_finalization">
|
|
<title>
|
|
Broker Finalization
|
|
</title>
|
|
<indexterm zone="ref_guide_runtime_broker_finalization">
|
|
<primary>
|
|
EntityManager
|
|
</primary>
|
|
<secondary>
|
|
finalizing
|
|
</secondary>
|
|
<tertiary>
|
|
clean-up
|
|
</tertiary>
|
|
</indexterm>
|
|
<para>
|
|
Outside of a Java EE 5 application server or other JPA persistence container
|
|
environment, the default OpenJPAEntityManager implementation automatically
|
|
closes itself during instance finalization. This guards against accidental
|
|
resource leaks that may occur if a developer fails to explicitly close
|
|
EntityManagers when finished with them, but it also incurs a scalability
|
|
bottleneck, since the JVM must perform synchronization during instance creation,
|
|
and since the finalizer thread will have more instances to monitor. To avoid
|
|
this overhead, set the
|
|
<link linkend="openjpa.BrokerImpl"><literal>openjpa.BrokerImpl</literal></link>
|
|
configuration property to <literal>non-finalizing</literal>.
|
|
</para>
|
|
</section>
|
|
<section id="ref_guide_runtime_broker_extension">
|
|
<title>
|
|
Broker Customization and Eviction
|
|
</title>
|
|
<indexterm zone="ref_guide_runtime_broker_extension">
|
|
<primary>
|
|
OpenJPAEntityManager
|
|
</primary>
|
|
<secondary>
|
|
extending
|
|
</secondary>
|
|
</indexterm>
|
|
<para>
|
|
As a <link linkend="ref_guide_conf_plugins">plugin string</link>, this property
|
|
can be used to configure the <classname> BrokerImpl</classname> with the
|
|
following properties:
|
|
</para>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>
|
|
<literal>EvictFromDataCache</literal>: When evicting an object through the
|
|
<methodname>OpenJPAEntityManager.evict</methodname> methods, whether to also
|
|
evict it from the OpenJPA's <link linkend="ref_guide_cache">data cache</link>.
|
|
Defaults to <literal>false</literal>.
|
|
</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
<example id="ref_guide_runtime_pm_evictex">
|
|
<title>
|
|
Evict from Data Cache
|
|
</title>
|
|
<programlisting>
|
|
<property name="openjpa.BrokerImpl" value="EvictFromDataCache=true"/>
|
|
</programlisting>
|
|
</example>
|
|
<para>
|
|
Additionally, some advanced users may want to add capabilities to OpenJPA's
|
|
internal <ulink url="../javadoc/org/apache/openjpa/kernel/BrokerImpl.html">
|
|
<classname>org.apache.openjpa.kernel.BrokerImpl</classname></ulink>. You can
|
|
configure OpenJPA to use a custom subclass of <classname>BrokerImpl</classname>
|
|
with the <link linkend="openjpa.BrokerImpl"><literal>openjpa.BrokerImpl
|
|
</literal></link> configuration property. Set this property to the full class
|
|
name of your custom subclass. When implementing your subclass, consider the
|
|
finalization issues mentioned in
|
|
<xref linkend="ref_guide_runtime_broker_finalization"/>. It may be appropriate
|
|
to create a subtype of both
|
|
<ulink url="../javadoc/org/apache/openjpa/kernel/BrokerImpl.html">
|
|
<classname>org.apache.openjpa.kernel.BrokerImpl</classname></ulink> and
|
|
<ulink url="../javadoc/org/apache/openjpa/kernel/FinalizingBrokerImpl.html">
|
|
<classname>org.apache.openjpa.kernel.FinalizingBrokerImpl</classname></ulink>.
|
|
</para>
|
|
</section>
|
|
</section>
|
|
<section id="ref_guide_runtime_jpa">
|
|
<title>
|
|
JPA Extensions
|
|
</title>
|
|
<para>
|
|
The following sections outline the runtime interfaces you can use to access
|
|
OpenJPA-specific functionality from JPA. Each interface contains services and
|
|
convenience methods missing from the JPA specification. OpenJPA strives to use
|
|
the same naming conventions and API patterns as standard JPA methods in all
|
|
extensions, so that OpenJPA extension APIs feel as much as possible like
|
|
standard JPA.
|
|
</para>
|
|
<para>
|
|
You may have noticed the examples throughout this document using the
|
|
<methodname>OpenJPAPersistence.cast</methodname> methods to cast from standard
|
|
JPA interfaces to OpenJPA extended interfaces. This is the recommended practice.
|
|
Some application server vendors may proxy OpenJPA's JPA implementation,
|
|
preventing a straight cast. <classname>OpenJPAPersistence</classname>'s
|
|
<methodname>cast</methodname> methods work around these proxies.
|
|
</para>
|
|
<programlisting>
|
|
public static OpenJPAEntityManagerFactory cast(EntityManagerFactory emf);
|
|
public static OpenJPAEntityManager cast(EntityManager em);
|
|
public static OpenJPAQuery cast(Query q);
|
|
</programlisting>
|
|
<para>
|
|
We provide additional information on the <classname>OpenJPAPersistence
|
|
</classname> helper <link linkend="ref_guide_runtime_openjpapersistence">
|
|
below</link>.
|
|
</para>
|
|
<section id="ref_guide_runtime_emfactory">
|
|
<title>
|
|
OpenJPAEntityManagerFactory
|
|
</title>
|
|
<indexterm zone="ref_guide_runtime_emfactory">
|
|
<primary>
|
|
OpenJPAEntityManagerFactory
|
|
</primary>
|
|
</indexterm>
|
|
<indexterm>
|
|
<primary>
|
|
EntityManagerFactory
|
|
</primary>
|
|
<secondary>
|
|
OpenJPA extensions
|
|
</secondary>
|
|
<see>
|
|
OpenJPAEntityManagerFactory
|
|
</see>
|
|
</indexterm>
|
|
<para>
|
|
The <classname>org.apache.openjpa.persistence.OpenJPAEntityManagerFactory
|
|
</classname> interface extends the basic <classname>
|
|
javax.persistence.EntityManagerFactory</classname> with OpenJPA-specific
|
|
features. The <classname>OpenJPAEntityManagerFactory</classname> offers APIs to
|
|
access the OpenJPA data and query caches and to perform other OpenJPA-specific
|
|
operations. See the
|
|
<ulink url="../javadoc/org/apache/openjpa/persistence/OpenJPAEntityManagerFactory.html">
|
|
interface Javadoc</ulink> for details.
|
|
</para>
|
|
</section>
|
|
<section id="ref_guide_runtime_em">
|
|
<title>
|
|
OpenJPAEntityManager
|
|
</title>
|
|
<indexterm zone="ref_guide_runtime_em">
|
|
<primary>
|
|
OpenJPAEntityManager
|
|
</primary>
|
|
</indexterm>
|
|
<indexterm>
|
|
<primary>
|
|
EntityManager
|
|
</primary>
|
|
<secondary>
|
|
OpenJPA extensions
|
|
</secondary>
|
|
<see>
|
|
OpenJPAEntityManager
|
|
</see>
|
|
</indexterm>
|
|
<para>
|
|
All OpenJPA <classname>EntityManager</classname>s implement the
|
|
<ulink url="../javadoc/org/apache/openjpa/persistence/OpenJPAEntityManager.html">
|
|
<classname>org.apache.openjpa.persistence.OpenJPAEntityManager</classname>
|
|
</ulink> interface. This interface extends the standard <classname>
|
|
javax.persistence.EntityManager</classname>. Just as the standard <classname>
|
|
EntityManager</classname> is the primary window into JPA services, the
|
|
<classname>OpenJPAEntityManager</classname> is the primary window from JPA into
|
|
OpenJPA-specific functionality. We strongly encourage you to investigate the API
|
|
extensions this interface contains.
|
|
</para>
|
|
</section>
|
|
<section id="ref_guide_runtime_jpaquery">
|
|
<title>
|
|
OpenJPAQuery
|
|
</title>
|
|
<indexterm zone="ref_guide_runtime_jpaquery">
|
|
<primary>
|
|
OpenJPAQuery
|
|
</primary>
|
|
</indexterm>
|
|
<indexterm>
|
|
<primary>
|
|
Query
|
|
</primary>
|
|
<secondary>
|
|
OpenJPA extensions
|
|
</secondary>
|
|
<see>
|
|
OpenJPAQuery
|
|
</see>
|
|
</indexterm>
|
|
<para>
|
|
OpenJPA extends JPA's standard query functionality with the <classname>
|
|
org.apache.openjpa.persistence.OpenJPAQuery</classname> interface. See its
|
|
<ulink url="../javadoc/org/apache/openjpa/persistence/OpenJPAQuery.html">Javadoc
|
|
</ulink> for details on the convenience methods it provides.
|
|
</para>
|
|
</section>
|
|
<section id="ref_guide_runtime_jpaextent">
|
|
<title>
|
|
Extent
|
|
</title>
|
|
<indexterm zone="ref_guide_runtime_jpaextent">
|
|
<primary>
|
|
Extent
|
|
</primary>
|
|
</indexterm>
|
|
<indexterm>
|
|
<primary>
|
|
Extent
|
|
</primary>
|
|
<secondary>
|
|
OpenJPA extensions
|
|
</secondary>
|
|
<see>
|
|
OpenJPAExtent
|
|
</see>
|
|
</indexterm>
|
|
<para>
|
|
An <classname>Extent</classname> is a logical view of all persistent instances
|
|
of a given entity class, possibly including subclasses. OpenJPA adds the
|
|
<ulink url="../javadoc/org/apache/openjpa/persistence/Extent.html"><classname>
|
|
org.apache.openjpa.persistence.Extent</classname></ulink> class to the set of
|
|
Java Persistence APIs. The following code illustrates iterating over all
|
|
instances of the <classname>Magazine</classname> entity, without subclasses:
|
|
</para>
|
|
<example id="ref_guide_runtime_jpaextentex">
|
|
<title>
|
|
Using a JPA Extent
|
|
</title>
|
|
<programlisting>
|
|
import org.apache.openjpa.persistence.*;
|
|
|
|
...
|
|
|
|
OpenJPAEntityManager kem = OpenJPAPersistence.cast(em);
|
|
Extent<Magazine> mags = kem.createExtent(Magazine.class, false);
|
|
for (Magazine m : mags)
|
|
processMagazine(m);
|
|
</programlisting>
|
|
</example>
|
|
</section>
|
|
<section id="ref_guide_runtime_jpacache">
|
|
<title>
|
|
StoreCache
|
|
</title>
|
|
<indexterm zone="ref_guide_runtime_jpacache">
|
|
<primary>
|
|
StoreCache
|
|
</primary>
|
|
</indexterm>
|
|
<para>
|
|
In addition to the <classname>EntityManager</classname> object cache the JPA
|
|
specification provides access to a second level cache via the
|
|
javax.persistence.Cache interface. OpenJPA provides further extensions via
|
|
the org.apache.openjpa.persistence.StoreCache interface documented at
|
|
<ulink url="../javadoc/org/apache/openjpa/persistence/StoreCache.html">
|
|
<classname>org.apache.openjpa.persistence.StoreCache</classname></ulink>.
|
|
<xref linkend="ref_guide_cache"/> has detailed information on OpenJPA's
|
|
data caching system, including the <classname>StoreCache</classname> facade.
|
|
</para>
|
|
</section>
|
|
<section id="ref_guide_runtime_jpaquerycache">
|
|
<title>
|
|
QueryResultCache
|
|
</title>
|
|
<indexterm zone="ref_guide_runtime_jpaquerycache">
|
|
<primary>
|
|
QueryResultCache
|
|
</primary>
|
|
</indexterm>
|
|
<para>
|
|
OpenJPA can cache query results as well as persistent object data. The
|
|
<ulink url="../javadoc/org/apache/openjpa/persistence/QueryResultCache.html">
|
|
<classname>org.apache.openjpa.persistence.QueryResultCache</classname></ulink>
|
|
is an JPA-flavored facade to OpenJPA's internal query cache. See
|
|
<xref linkend="ref_guide_cache_query"/> for details on query caching in
|
|
OpenJPA.
|
|
</para>
|
|
</section>
|
|
<section id="ref_guide_runtime_jpafetch">
|
|
<title>
|
|
FetchPlan
|
|
</title>
|
|
<indexterm zone="ref_guide_runtime_jpafetch">
|
|
<primary>
|
|
FetchPlan
|
|
</primary>
|
|
</indexterm>
|
|
<indexterm>
|
|
<primary>
|
|
eager fetching
|
|
</primary>
|
|
<seealso>
|
|
FetchPlan
|
|
</seealso>
|
|
</indexterm>
|
|
<para>
|
|
Many of the aforementioned OpenJPA interfaces give you access to an <classname>
|
|
org.apache.openjpa.persistence.FetchPlan</classname> instance. The <classname>
|
|
FetchPlan</classname> allows you to exercise some control over how objects are
|
|
fetched from the datastore, including <link linkend="ref_guide_dbsetup_lrs">
|
|
large result set support</link>, <link linkend="ref_guide_fetch">custom fetch
|
|
groups</link>, and <link linkend="ref_guide_locking">lock levels</link>.
|
|
</para>
|
|
<para>
|
|
OpenJPA goes one step further, extending <classname>FetchPlan</classname> with
|
|
<ulink url="../javadoc/org/apache/openjpa/persistence/jdbc/JDBCFetchPlan.html">
|
|
<classname>org.apache.openjpa.persistence.jdbc.JDBCFetchPlan</classname></ulink>
|
|
to add additional JDBC-specific tuning methods. Unless you have customized
|
|
OpenJPA to use a non-relational back-end (see
|
|
<xref linkend="ref_guide_enterprise_abstractstore"/> ), all <classname>
|
|
FetchPlan</classname>s in OpenJPA implement <classname>
|
|
JDBCFetchPlan</classname>, so feel free to cast to this interface.
|
|
</para>
|
|
<para>
|
|
Fetch plans pass on from parent components to child components. The <classname>
|
|
EntityManagerFactory</classname> settings (via your configuration properties)
|
|
for things like the fetch size, result set type, and custom fetch groups are
|
|
passed on to the fetch plan of the <classname>EntityManager</classname>s it
|
|
produces. The settings of each <classname>EntityManager</classname>, in turn,
|
|
are passed on to each <classname>Query</classname> and <classname>Extent
|
|
</classname> it returns. Note that the opposite, however, is not true. Modifying
|
|
the fetch plan of a <classname>Query</classname> or <classname>Extent
|
|
</classname> does not affect the <classname>EntityManager</classname>'s
|
|
configuration. Likewise, modifying an <classname>EntityManager</classname>'s
|
|
configuration does not affect the <classname> EntityManagerFactory</classname>.
|
|
</para>
|
|
<para>
|
|
<xref linkend="ref_guide_fetch"/> includes examples using <classname>
|
|
FetchPlan</classname>s.
|
|
</para>
|
|
</section>
|
|
<section id="ref_guide_runtime_openjpaentitytransaction">
|
|
<title>
|
|
OpenJPAEntityTransaction
|
|
</title>
|
|
<indexterm zone="ref_guide_runtime_openjpaentitytransaction">
|
|
<primary>
|
|
OpenJPAEntityTransaction
|
|
</primary>
|
|
</indexterm>
|
|
<para>
|
|
<ulink url="../javadoc/org/apache/openjpa/persistence/OpenJPAEntityTransaction.html">
|
|
<classname>org.apache.openjpa.persistence.OpenJPAEntityTransaction</classname></ulink>
|
|
extends <classname>javax.persistence.EntityTransaction</classname> to provide
|
|
additional transaction-debugging capabilities and some concurrency-related
|
|
commit and rollback features.
|
|
</para>
|
|
</section>
|
|
<section id="ref_guide_runtime_openjpapersistence">
|
|
<title>
|
|
OpenJPAPersistence
|
|
</title>
|
|
<indexterm zone="ref_guide_runtime_openjpapersistence">
|
|
<primary>
|
|
OpenJPAPersistence
|
|
</primary>
|
|
</indexterm>
|
|
<para>
|
|
<ulink url="../javadoc/org/apache/openjpa/persistence/OpenJPAPersistence.html">
|
|
<classname>org.apache.openjpa.persistence.OpenJPAPersistence</classname></ulink>
|
|
is a static helper class that adds OpenJPA-specific utility methods to
|
|
<classname>javax.persistence.Persistence</classname>.
|
|
</para>
|
|
</section>
|
|
</section>
|
|
<section id="ref_guide_locking">
|
|
<title>
|
|
Object Locking
|
|
</title>
|
|
<indexterm zone="ref_guide_locking">
|
|
<primary>
|
|
locking
|
|
</primary>
|
|
</indexterm>
|
|
<para>
|
|
Controlling how and when objects are locked is an important part of maximizing
|
|
the performance of your application under load. This section describes OpenJPA's
|
|
APIs for explicit locking, as well as its rules for implicit locking.
|
|
</para>
|
|
<section id="ref_guide_locking_default">
|
|
<title>
|
|
Configuring Default Locking
|
|
</title>
|
|
<indexterm zone="ref_guide_locking_default">
|
|
<primary>
|
|
locking
|
|
</primary>
|
|
<secondary>
|
|
defaults configuration
|
|
</secondary>
|
|
</indexterm>
|
|
<para>
|
|
<indexterm>
|
|
<primary>
|
|
locking
|
|
</primary>
|
|
<secondary>
|
|
levels
|
|
</secondary>
|
|
</indexterm>
|
|
<indexterm>
|
|
<primary>
|
|
ReadLockLevel
|
|
</primary>
|
|
</indexterm>
|
|
<indexterm>
|
|
<primary>
|
|
WriteLockLevel
|
|
</primary>
|
|
</indexterm>
|
|
You can control OpenJPA's default transactional read and write lock levels
|
|
through the <link linkend="openjpa.ReadLockLevel"><literal>
|
|
openjpa.ReadLockLevel</literal></link> and
|
|
<link linkend="openjpa.WriteLockLevel"><literal>openjpa.WriteLockLevel</literal>
|
|
</link> configuration properties. Each property accepts a value of <literal>
|
|
none</literal>, <literal>read</literal>, <literal>write</literal>,
|
|
<literal>optimistic</literal>, <literal>optimistic-force-increment</literal>,
|
|
<literal>pessimistic-read</literal>, <literal>pessimistic-write</literal>,
|
|
<literal>pessimistic-force-increment</literal>, or a number
|
|
corresponding to a lock level defined by the
|
|
<link linkend="ref_guide_locking_lockmgr">lock manager</link> in use. These
|
|
properties apply only to non-optimistic transactions; during optimistic
|
|
transactions, OpenJPA never locks objects by default.
|
|
</para>
|
|
<para>
|
|
<indexterm>
|
|
<primary>
|
|
LockTimeout
|
|
</primary>
|
|
</indexterm>
|
|
<indexterm>
|
|
<primary>
|
|
locking
|
|
</primary>
|
|
<secondary>
|
|
timeout
|
|
</secondary>
|
|
</indexterm>
|
|
You can control the default amount of time OpenJPA will wait when trying to
|
|
obtain locks through the <link linkend="openjpa.LockTimeout"><literal>
|
|
openjpa.LockTimeout</literal></link> configuration property. Set this property
|
|
to the number of milliseconds you are willing to wait for a lock before OpenJPA
|
|
will throw an exception, or to -1 for no limit. It defaults to -1.
|
|
</para>
|
|
<example id="ref_guide_locking_default_conf">
|
|
<title>
|
|
Setting Default Lock Levels
|
|
</title>
|
|
<programlisting>
|
|
<property name="openjpa.ReadLockLevel" value="none"/>
|
|
<property name="openjpa.WriteLockLevel" value="write"/>
|
|
<property name="openjpa.LockTimeout" value="30000"/>
|
|
</programlisting>
|
|
</example>
|
|
</section>
|
|
<section id="ref_guide_locking_runtime">
|
|
<title>
|
|
Configuring Lock Levels at Runtime
|
|
</title>
|
|
<indexterm zone="ref_guide_locking_runtime">
|
|
<primary>
|
|
locking
|
|
</primary>
|
|
<secondary>
|
|
runtime configuration
|
|
</secondary>
|
|
</indexterm>
|
|
<para>
|
|
At runtime, you can override the default lock levels through the <classname>
|
|
FetchPlan</classname> interface described above. At the beginning of each
|
|
datastore transaction, OpenJPA initializes the <classname> EntityManager
|
|
</classname>'s fetch plan with the default lock levels and timeouts described
|
|
in the previous section. By changing the fetch plan's locking properties, you
|
|
can control how objects loaded at different points in the transaction are
|
|
locked. You can also use the fetch plan of an individual <classname>Query
|
|
</classname> to apply your locking changes only to objects loaded through that
|
|
<classname>Query</classname>.
|
|
</para>
|
|
<programlisting>
|
|
public LockModeType getReadLockMode();
|
|
public FetchPlan setReadLockMode(LockModeType mode);
|
|
public LockModeType getWriteLockMode();
|
|
public FetchPlan setWriteLockMode(LockModeType mode);
|
|
long getLockTimeout();
|
|
FetchPlan setLockTimeout(long timeout);
|
|
</programlisting>
|
|
<para>
|
|
Controlling locking through these runtime APIs works even during optimistic
|
|
transactions. At the end of the transaction, OpenJPA resets the fetch plan's
|
|
lock levels to <literal>none</literal>. You cannot lock objects outside of a
|
|
transaction.
|
|
</para>
|
|
<example id="ref_guide_locking_fetch">
|
|
<title>
|
|
Setting Runtime Lock Levels
|
|
</title>
|
|
<programlisting>
|
|
import org.apache.openjpa.persistence.*;
|
|
|
|
...
|
|
|
|
EntityManager em = ...;
|
|
em.getTransaction().begin();
|
|
|
|
// load stock we know we're going to update at write lock mode
|
|
Query q = em.createQuery("select s from Stock s where symbol = :s");
|
|
q.setParameter("s", symbol);
|
|
OpenJPAQuery oq = OpenJPAPersistence.cast(q);
|
|
FetchPlan fetch = oq.getFetchPlan();
|
|
fetch.setReadLockMode(LockModeType.WRITE);
|
|
fetch.setLockTimeout(3000); // 3 seconds
|
|
Stock stock = (Stock) q.getSingleResult();
|
|
|
|
// load an object we don't need locked at none lock mode
|
|
fetch = OpenJPAPersistence.cast(em).getFetchPlan();
|
|
fetch.setReadLockMode(null);
|
|
Market market = em.find(Market.class, marketId);
|
|
|
|
stock.setPrice(market.calculatePrice(stock));
|
|
em.getTransaction().commit();
|
|
</programlisting>
|
|
</example>
|
|
</section>
|
|
<section id="ref_guide_locking_apis">
|
|
<title>
|
|
Object Locking APIs
|
|
</title>
|
|
<indexterm zone="ref_guide_locking_apis">
|
|
<primary>
|
|
locking
|
|
</primary>
|
|
<secondary>
|
|
runtime APIs
|
|
</secondary>
|
|
</indexterm>
|
|
<para>
|
|
In addition to allowing you to control implicit locking levels, OpenJPA provides
|
|
explicit APIs to lock objects and to retrieve their current lock level.
|
|
</para>
|
|
<programlisting>
|
|
public LockModeType OpenJPAEntityManager.getLockMode(Object pc);
|
|
</programlisting>
|
|
<para>
|
|
Returns the level at which the given object is currently locked.
|
|
</para>
|
|
<para>
|
|
In addition to the standard
|
|
<ulink url="http://java.sun.com/javaee/6/docs/api/javax/persistence/EntityManager.html">
|
|
<methodname>EntityManager.lock(Object, LockModeType)</methodname></ulink>
|
|
method, the
|
|
<ulink url="../javadoc/org/apache/openjpa/persistence/OpenJPAEntityManager.html">
|
|
<classname>OpenJPAEntityManager</classname></ulink> exposes the following
|
|
methods to lock objects explicitly:
|
|
</para>
|
|
<programlisting>
|
|
public void lock(Object pc);
|
|
public void lock(Object pc, LockModeType mode, long timeout);
|
|
public void lockAll(Object... pcs);
|
|
public void lockAll(Object... pcs, LockModeType mode, long timeout);
|
|
public void lockAll(Collection pcs);
|
|
public void lockAll(Collection pcs, LockModeType mode, long timeout);
|
|
</programlisting>
|
|
<para>
|
|
Methods that do not take a lock level or timeout parameter default to the
|
|
current fetch plan. The example below demonstrates these methods in action.
|
|
</para>
|
|
<example id="ref_guide_locking_explicit">
|
|
<title>
|
|
Locking APIs
|
|
</title>
|
|
<programlisting>
|
|
import org.apache.openjpa.persistence.*;
|
|
|
|
// retrieve the lock level of an object
|
|
OpenJPAEntityManager oem = OpenJPAPersistence.cast(em);
|
|
Stock stock = ...;
|
|
LockModeType level = oem.getLockMode(stock);
|
|
if (level == OpenJPAModeType.WRITE) ...
|
|
|
|
...
|
|
|
|
oem.setOptimistic(true);
|
|
oem.getTransaction().begin();
|
|
|
|
// override default of not locking during an opt trans to lock stock object
|
|
oem.lock(stock, LockModeType.WRITE, 1000);
|
|
stock.setPrice(market.calculatePrice(stock));
|
|
|
|
oem.getTransaction().commit();
|
|
</programlisting>
|
|
</example>
|
|
</section>
|
|
<section id="ref_guide_locking_lockmgr">
|
|
<title>
|
|
Lock Manager
|
|
</title>
|
|
<indexterm zone="ref_guide_locking_lockmgr">
|
|
<primary>
|
|
locking
|
|
</primary>
|
|
<secondary>
|
|
LockManager
|
|
</secondary>
|
|
</indexterm>
|
|
<para>
|
|
<indexterm>
|
|
<primary>
|
|
LockManager
|
|
</primary>
|
|
</indexterm>
|
|
OpenJPA delegates the actual work of locking objects to the system's
|
|
<ulink url="../javadoc/org/apache/openjpa/kernel/LockManager.html"><classname>
|
|
org.apache.openjpa.kernel.LockManager</classname></ulink>. This plugin is
|
|
controlled by the <link linkend="openjpa.LockManager"><literal>
|
|
openjpa.LockManager</literal></link> configuration property. You can write your
|
|
own lock manager, or use one of the bundled options:
|
|
</para>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>
|
|
<literal>mixed</literal>: This is an alias for the
|
|
<ulink url="../javadoc/org/apache/openjpa/jdbc/kernel/MixedLockManager.html">
|
|
<classname>org.apache.openjpa.jdbc.kernel.MixedLockManager</classname>
|
|
</ulink>, which implements the JPA 2.0 specification entity locking behaviors.
|
|
It combines both the optimistic and pessimistic semantics controlled by
|
|
lock mode argument in methods define in the EntityManager
|
|
and Query interfaces or OpenJPA lock level properties.
|
|
</para>
|
|
<para>
|
|
The <literal>mixed</literal> LockManager inherits all the properties available
|
|
from <literal>version</literal> and <literal>pessimistic</literal> LockManagers.
|
|
For example: <literal>VersionCheckOnReadLock</literal> and
|
|
<literal>VersionUpdateOnWriteLock</literal> properties.
|
|
</para>
|
|
<para>
|
|
This is the default <literal>openjpa.LockManager</literal> setting in OpenJPA.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<literal>pessimistic</literal>: This is an alias for the
|
|
<ulink
|
|
url="../javadoc/org/apache/openjpa/jdbc/kernel/PessimisticLockManager.html">
|
|
<classname>org.apache.openjpa.jdbc.kernel.PessimisticLockManager</classname>
|
|
</ulink>, which
|
|
uses SELECT FOR UPDATE statements (or the database's equivalent) to lock the
|
|
database rows corresponding to locked objects. This lock
|
|
manager does not distinguish between read locks and write locks; all locks are
|
|
write locks.
|
|
</para>
|
|
<para>
|
|
The <literal>pessimistic</literal> LockManager can be configured to additionally
|
|
perform the version checking and incrementing behavior of the <literal>version
|
|
</literal> lock manager described below by setting its <literal>
|
|
VersionCheckOnReadLock</literal> and <literal>VersionUpdateOnWriteLock</literal>
|
|
properties:
|
|
</para>
|
|
<programlisting>
|
|
<property name="openjpa.LockManager" value="pessimistic(VersionCheckOnReadLock=true,VersionUpdateOnWriteLock=true)"/>
|
|
</programlisting>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<literal>version</literal>: This is an alias for the
|
|
<ulink url="../javadoc/org/apache/openjpa/kernel/VersionLockManager.html">
|
|
<classname>org.apache.openjpa.kernel.VersionLockManager</classname></ulink>.
|
|
This lock manager does not perform any exclusive locking, but instead ensures
|
|
read consistency by verifying that the version of all read-locked instances is
|
|
unchanged at the end of the transaction. Furthermore, a write lock will force an
|
|
increment to the version at the end of the transaction, even if the object is
|
|
not otherwise modified. This ensures read consistency with non-blocking
|
|
behavior.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<literal>none</literal>: This is an alias for the
|
|
<ulink url="../javadoc/org/apache/openjpa/kernel/NoneLockManager.html">
|
|
<classname>org.apache.openjpa.kernel.NoneLockManager</classname></ulink>, which
|
|
does not perform any locking at all.
|
|
</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
<note>
|
|
<para>
|
|
In order for the <literal>version</literal> or <literal>mixed</literal> lock
|
|
managers to prevent the dirty
|
|
read phenomenon, the underlying data store's transaction isolation level must be
|
|
set to the equivalent of "read committed" or higher.
|
|
</para>
|
|
</note>
|
|
<example id="ref_guide_locking_disable">
|
|
<title>
|
|
Disabling Locking
|
|
</title>
|
|
<programlisting>
|
|
<property name="openjpa.LockManager" value="none"/>
|
|
</programlisting>
|
|
</example>
|
|
</section>
|
|
<section id="ref_guide_locking_rules">
|
|
<title>
|
|
Rules for Locking Behavior
|
|
</title>
|
|
<indexterm zone="ref_guide_locking_rules">
|
|
<primary>
|
|
locking
|
|
</primary>
|
|
<secondary>
|
|
behavior
|
|
</secondary>
|
|
</indexterm>
|
|
<indexterm zone="ref_guide_locking_rules">
|
|
<primary>
|
|
lazy loading
|
|
</primary>
|
|
<secondary>
|
|
locking behavior
|
|
</secondary>
|
|
</indexterm>
|
|
<para>
|
|
Advanced persistence concepts like lazy-loading and object uniquing create
|
|
several locking corner-cases. The rules below outline OpenJPA's implicit locking
|
|
behavior in these cases.
|
|
</para>
|
|
<orderedlist>
|
|
<listitem>
|
|
<para>
|
|
When an object's state is first read within a transaction, the object is locked
|
|
at the fetch plan's current read lock level. Future reads of additional lazy
|
|
state for the object will use the same read lock level, even if the fetch plan's
|
|
level has changed.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
When an object's state is first modified within a transaction, the object is
|
|
locked at the write lock level in effect when the object was first read, even if
|
|
the fetch plan's level has changed. If the object was not read previously, the
|
|
current write lock level is used.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
When objects are accessed through a persistent relation field, the related
|
|
objects are loaded with the fetch plan's current lock levels, not the lock
|
|
levels of the object owning the field.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
Whenever an object is accessed within a transaction, the object is re-locked at
|
|
the current read lock level. The current read and write lock levels become those
|
|
that the object "remembers" according to rules one and two above.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
If you lock an object explicitly through the APIs demonstrated above, it is
|
|
re-locked at the specified level. This level also becomes both the read and
|
|
write level that the object "remembers" according to rules one and two above.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
When an object is already locked at a given lock level, re-locking at a lower
|
|
level has no effect. Locks cannot be downgraded during a transaction.
|
|
</para>
|
|
</listitem>
|
|
</orderedlist>
|
|
</section>
|
|
<section id="ref_guide_locking_issues">
|
|
<title>
|
|
Known Issues and Limitations
|
|
</title>
|
|
<indexterm zone="ref_guide_locking_issues">
|
|
<primary>
|
|
locking
|
|
</primary>
|
|
<secondary>
|
|
caveats
|
|
</secondary>
|
|
</indexterm>
|
|
<para>
|
|
Due to performance concerns and database limitations, locking cannot be perfect.
|
|
You should be aware of the issues outlined in this section, as they may affect
|
|
your application.
|
|
</para>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>
|
|
Typically, during optimistic transactions OpenJPA does not start an actual
|
|
database transaction until you flush or the optimistic transaction commits. This
|
|
allows for very long-lived transactions without consuming database resources.
|
|
When using the pessimistic lock manager, however, OpenJPA must begin a database
|
|
transaction whenever you decide to lock an object during an optimistic
|
|
transaction. This is because the pessimistic lock manager uses database locks,
|
|
and databases cannot lock rows without a transaction in progress. OpenJPA will
|
|
log an INFO message to the <literal>openjpa.Runtime</literal> logging channel
|
|
when it begins a datastore transaction just to lock an object.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
In order to maintain reasonable performance levels when loading object state,
|
|
OpenJPA can only guarantee that an object is locked at the proper lock level
|
|
<emphasis>after</emphasis> the state has been retrieved from the database. This
|
|
means that it is technically possible for another transaction to "sneak in" and
|
|
modify the database record after OpenJPA retrieves the state, but before it
|
|
locks the object. The only way to positively guarantee that the object is locked
|
|
and has the most recent state to refresh the object after locking it.
|
|
</para>
|
|
<para>
|
|
When using the pessimistic lock manager, the case above can only occur when
|
|
OpenJPA cannot issue the state-loading SELECT as a locking statement due to
|
|
database limitations. For example, some databases cannot lock SELECTs that use
|
|
joins. The pessimistic lock manager will log an INFO message to the <literal>
|
|
openjpa.Runtime</literal> logging channel whenever it cannot lock the initial
|
|
SELECT due to database limitations. By paying attention to these log messages,
|
|
you can see where you might consider using an object refresh to guarantee that
|
|
you have the most recent state, or where you might rethink the way you load the
|
|
state in question to circumvent the database limitations that prevent OpenJPA
|
|
from issuing a locking SELECT in the first place.
|
|
</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
</section>
|
|
<section id="ref_guide_savepoints">
|
|
<title>
|
|
Savepoints
|
|
</title>
|
|
<indexterm zone="ref_guide_savepoints">
|
|
<primary>
|
|
savepoint
|
|
</primary>
|
|
</indexterm>
|
|
<para>
|
|
Savepoints allow for fine grained control over the transactional behavior of
|
|
your application. OpenJPA's savepoint API allow you to set intermediate rollback
|
|
points in your transaction. You can then choose to rollback changes made only
|
|
after a specific savepoint, then commit or continue making new changes in the
|
|
transaction. This feature is useful for multi-stage transactions, such as
|
|
editing a set of objects over several web pages or user screens. Savepoints also
|
|
provide more flexibility to conditional transaction behavior, such as choosing to
|
|
commit or rollback a portion of the transaction based on the results of the
|
|
changes. This chapter describes how to use and configure OpenJPA savepoints.
|
|
</para>
|
|
<section id="reg_guide_savepoints_using">
|
|
<title>
|
|
Using Savepoints
|
|
</title>
|
|
<para>
|
|
OpenJPA's
|
|
<ulink url="../javadoc/org/apache/openjpa/persistence/OpenJPAEntityManager.html">
|
|
<classname>OpenJPAEntityManager</classname></ulink> have the following
|
|
methods to control savepoint behavior. Note that the savepoints work in tandem
|
|
with the current transaction. This means that savepoints require an open
|
|
transaction, and that a rollback of the transaction will rollback all of the
|
|
changes in the transaction regardless of any savepoints set.
|
|
</para>
|
|
<programlisting>
|
|
void setSavepoint(String name);
|
|
void releaseSavepoint(String name);
|
|
void rollbackToSavepoint(String name);
|
|
</programlisting>
|
|
<para>
|
|
To set a savepoint, simply call <methodname>setSavepoint</methodname>, passing
|
|
in a symbolic savepoint name. This savepoint will define a point at which you
|
|
can preserve the state of transactional objects for the duration of the current
|
|
transaction.
|
|
</para>
|
|
<para>
|
|
Having set a named savepoint, you can rollback changes made after that point by
|
|
calling <methodname>rollbackToSavepoint</methodname>. This method will keep the
|
|
current transaction active, while restoring all transactional instances back to
|
|
their saved state. Instances that were deleted after the save point will no
|
|
longer be marked for deletion. Similarly, transient instances that were made
|
|
persistent after the savepoint will become transient again. Savepoints made
|
|
after this savepoint will be released and no longer valid, although you can
|
|
still set new savepoints. Savepoints will also be cleared after the current
|
|
transaction is committed or rolled back.
|
|
</para>
|
|
<para>
|
|
If a savepoint is no longer needed, you can release any resources it is
|
|
consuming resources by calling <methodname>releaseSavepoint</methodname>. This
|
|
method should not be called for savepoints that have been
|
|
released automatically through other means, such as commit of a transaction or
|
|
rollback to a prior savepoint. While savepoints made after this savepoint will
|
|
also be released, there are no other effects on the current transaction.
|
|
</para>
|
|
<para>
|
|
The following simple example illustrates setting, releasing, and rolling back to
|
|
a savepoint.
|
|
</para>
|
|
<example id="ref_guide_savepoints_example">
|
|
<title>
|
|
Using Savepoints
|
|
</title>
|
|
<programlisting>
|
|
import org.apache.openjpa.persistence.*;
|
|
|
|
...
|
|
|
|
OpenJPAEntityManager oem = OpenJPAPersistence.cast(em);
|
|
oem.getTransaction().begin();
|
|
|
|
Magazine mag = oem.find(Magazine.class, id);
|
|
mag.setPageCount(300);
|
|
oem.setSavepoint("pages");
|
|
|
|
mag.setPrice(mag.getPageCount() * pricePerPage);
|
|
// we decide to release "pages"...
|
|
oem.releaseSavepoint("pages");
|
|
// ... and set a new savepoint which includes all changes
|
|
oem.setSavepoint("price");
|
|
|
|
mag.setPrice(testPrice);
|
|
// we determine the test price is not good
|
|
oem.rollbackToSavepoint("price");
|
|
// had we chosen to not release "pages", we might have rolled back to
|
|
// "pages" instead
|
|
|
|
// the price is now restored to mag.getPageCount() * pricePerPage
|
|
oem.getTransaction().commit();
|
|
</programlisting>
|
|
</example>
|
|
</section>
|
|
<section id="ref_guide_savepoints_conf">
|
|
<title>
|
|
Configuring Savepoints
|
|
</title>
|
|
<para>
|
|
OpenJPA uses the
|
|
<ulink url="../javadoc/org/apache/openjpa/kernel/SavepointManager">
|
|
<classname>org.apache.openjpa.kernel.SavepointManager</classname></ulink>
|
|
<link linkend="ref_guide_conf_plugins">plugin</link> to handle preserving the
|
|
savepoint state. OpenJPA includes the following <classname>SavepointManager
|
|
</classname> plugins:
|
|
</para>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>
|
|
<literal>in-mem</literal>: The default. This is an alias for the
|
|
<ulink url="org.apache.openjpa.kernel.InMemorySavepointManager"><classname>
|
|
org.apache.openjpa.kernel.InMemorySavepointManager</classname></ulink>. This
|
|
plugin stores all state, including field values, in memory. Due to this
|
|
behavior, each set savepoint is designed for small to medium transactional
|
|
object counts.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<literal>jdbc</literal>: This is an alias for the
|
|
<ulink url="org.apache.openjpa.jdbc.kernel.JDBCSavepointManager"><classname>
|
|
org.apache.openjpa.jdbc.kernel.JDBCSavepointManager</classname></ulink>. This
|
|
plugin requires <literal>JDBC 3</literal> and <classname> java.sql.Savepoint
|
|
</classname> support to operate. Note that this plugin implements savepoints by
|
|
issuing a flush to the database.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<literal>oracle</literal>: This is an alias for the
|
|
<ulink url="org.apache.openjpa.jdbc.sql.OracleSavepointManager"><classname>
|
|
org.apache.openjpa.jdbc.sql.OracleSavepointManager</classname></ulink>. This
|
|
plugin operates similarly to the <literal>JDBC</literal> plugin; however, it
|
|
uses Oracle-specific calls. This plugin requires using the Oracle JDBC driver
|
|
and database, versions <literal>9.2</literal> or higher. Note that this plugin
|
|
implements savepoints by issuing a flush to the database.
|
|
</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
</section>
|
|
<!--
|
|
<section id="ref_guide_enterprise_queryext">
|
|
<title>
|
|
Query Language Extensions
|
|
</title>
|
|
<indexterm zone="ref_guide_enterprise_queryext">
|
|
<primary>
|
|
Query
|
|
</primary>
|
|
<secondary>
|
|
language extensions
|
|
</secondary>
|
|
<seealso>
|
|
JPQL
|
|
</seealso>
|
|
</indexterm>
|
|
<para>
|
|
JPQL is a powerful, easy-to-use query language, but you may occasionally find it
|
|
limiting in some way. To circumvent the limitations of JPQL, OpenJPA provides
|
|
extensions to the JPQL language, and allows you to extend it as well.
|
|
</para>
|
|
<warning>
|
|
<para>
|
|
The JPQL parser in this release does not yet allow extensions. They will be made
|
|
available to JPQL users in a future release.
|
|
</para>
|
|
</warning>
|
|
<section id="ref_guide_enterprise_queryext_jdoql">
|
|
<title>
|
|
Filter Extensions
|
|
</title>
|
|
<indexterm zone="ref_guide_enterprise_queryext_jdoql">
|
|
<primary>
|
|
JPQL
|
|
</primary>
|
|
<secondary>
|
|
language extension
|
|
</secondary>
|
|
</indexterm>
|
|
<para>
|
|
Filter extensions are custom methods that you can use in your query filter,
|
|
having, ordering, and result strings. OpenJPA provides some built-in filter
|
|
extensions, and you can develop your own custom extensions as needed. You can
|
|
optionally preface all filter extensions with <literal>ext:</literal> in your
|
|
query string. For example, the following example uses a hypothetical <literal>
|
|
firstThreeChars</literal> extension to search for cities whose name begins with
|
|
the 3 characters 'H', 'a', 'r'.
|
|
</para>
|
|
<example id="ref_guide_enterprise_queryext_jdoql_ext">
|
|
<title>
|
|
Basic Filter Extension
|
|
</title>
|
|
<programlisting>
|
|
Query q = em.createQuery("select c from City c where c.name.ext:firstThreeChars () = 'Har'");
|
|
List results = q.getResultList();
|
|
</programlisting>
|
|
</example>
|
|
<para>
|
|
Note that it is perfectly OK to chain together extensions. For example, let's
|
|
modify our search above to be case-insensitive using another hypothetical
|
|
extension, <literal>equalsIgnoreCase</literal>:
|
|
</para>
|
|
<example id="ref_guide_enterprise_queryext_jdoql_chain">
|
|
<title>
|
|
Chaining Filter Extensions
|
|
</title>
|
|
<programlisting>
|
|
Query query = em.createQuery("select c from City c where "
|
|
+ "c.name.ext:firstThreeChars ().ext:equalsIgnoreCase ('Har')");
|
|
List results = q.getResultList();
|
|
</programlisting>
|
|
</example>
|
|
<para>
|
|
Finally, when using filter extensions you must be aware that any SQL-specific
|
|
extensions can only execute against the database, and cannot be used for
|
|
in-memory queries (recall that OpenJPA executes queries in-memory when you
|
|
supply a candidate collection rather than a class, or when you set the <literal>
|
|
IgnoreChanges</literal> and <literal>FlushBeforeQueries</literal> properties to
|
|
<literal>false</literal> and you execute a query within a transaction in which
|
|
you've modified data that may affect the results).
|
|
</para>
|
|
<section id="ref_guide_enterprise_queryext_jdoql_included">
|
|
<title>
|
|
Included Filter Extensions
|
|
</title>
|
|
<para>
|
|
OpenJPA includes two default filter extensions to enhance the power of your
|
|
queries.
|
|
</para>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>
|
|
<indexterm>
|
|
<primary>
|
|
JPQL
|
|
</primary>
|
|
<secondary>
|
|
language extension
|
|
</secondary>
|
|
<tertiary>
|
|
getColumn
|
|
</tertiary>
|
|
</indexterm>
|
|
<literal>getColumn</literal>: Places the proper alias for the given column name
|
|
into the SELECT statement that is issued. This extension cannot be used for
|
|
in-memory queries. When traversing relations, the column is assumed to be in the
|
|
primary table of the related type.
|
|
</para>
|
|
<programlisting>
|
|
select e from Employee e where e.company.address.ext:getColumn ('ID') = 5
|
|
</programlisting>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<indexterm>
|
|
<primary>
|
|
JPQL
|
|
</primary>
|
|
<secondary>
|
|
language extension
|
|
</secondary>
|
|
<tertiary>
|
|
sql
|
|
</tertiary>
|
|
</indexterm>
|
|
<literal>sql</literal>: Embeds the given SQL argument into the SELECT
|
|
statement. This extension cannot be used for in-memory queries.
|
|
</para>
|
|
<programlisting>
|
|
select p from Product p where p.price < ext:sql ('(SELECT AVG(PRICE) FROM PRODUCTS)')
|
|
</programlisting>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
<section id="ref_guide_enterprise_queryext_jdoql_custom">
|
|
<title>
|
|
Developing Custom Filter Extensions
|
|
</title>
|
|
<indexterm zone="ref_guide_enterprise_queryext_jdoql_custom">
|
|
<primary>
|
|
JPQL
|
|
</primary>
|
|
<secondary>
|
|
language extension
|
|
</secondary>
|
|
<tertiary>
|
|
custom
|
|
</tertiary>
|
|
</indexterm>
|
|
<para>
|
|
You can write your own extensions by implementing the
|
|
<ulink url="../javadoc/org/apache/openjpa/jdbc/kernel/exps/JDBCFilterListener.html">
|
|
<classname>org.apache.openjpa.jdbc.kernel.exps.JDBCFilterListener</classname>
|
|
</ulink> interface. View the Javadoc documentation for details. Additionally,
|
|
the source for all of OpenJPA's built-in query extensions is included in your
|
|
OpenJPA download to get you started. The built-in extensions reside in the
|
|
<filename> src/openjpa/kernel/exps</filename> and <filename>
|
|
src/openjpa/jdbc/kernel/exps</filename> directories of your distribution.
|
|
</para>
|
|
</section>
|
|
<section id="ref_guide_enterprise_queryext_jdoql_conf">
|
|
<title>
|
|
Configuring Filter Extensions
|
|
</title>
|
|
<indexterm zone="ref_guide_enterprise_queryext_jdoql_conf">
|
|
<primary>
|
|
JPQL
|
|
</primary>
|
|
<secondary>
|
|
language extension
|
|
</secondary>
|
|
<tertiary>
|
|
configuration
|
|
</tertiary>
|
|
</indexterm>
|
|
<para>
|
|
There are two ways to register your custom filter extensions with OpenJPA:
|
|
</para>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>
|
|
<emphasis>Registration by properties:</emphasis> You can register custom filter
|
|
extensions by setting the <link linkend="openjpa.FilterListeners"><literal>
|
|
openjpa.FilterListeners</literal></link> configuration property to a
|
|
comma-separated list of plugin strings (see
|
|
<xref linkend="ref_guide_conf_plugins"/>) describing your extensions
|
|
classes. Extensions registered in this fashion must have a public no-arg
|
|
constructor. They must also be thread safe, because they will be shared across
|
|
all queries.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<emphasis>Per-query registration:</emphasis> You can register filter extensions
|
|
for an individual <classname>Query</classname> through the <methodname>
|
|
OpenJPAQuery.addFilterListener</methodname> method. You might use per-query
|
|
registration for very specific extensions that do not apply globally.
|
|
</para>
|
|
<para>
|
|
See the <classname>OpenJPAQuery</classname>
|
|
<ulink url="../javadoc/org/apache/openjpa/persistence/OpenJPAQuery.html">
|
|
Javadoc</ulink> for details.
|
|
</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
</section>
|
|
<section id="ref_guide_aggregates_custom">
|
|
<title>
|
|
Aggregate Extensions
|
|
</title>
|
|
<indexterm zone="ref_guide_aggregates_custom">
|
|
<primary>
|
|
JPQL
|
|
</primary>
|
|
<secondary>
|
|
aggregate extension
|
|
</secondary>
|
|
</indexterm>
|
|
<para>
|
|
Just as you can write your own filter methods, you can write your own query
|
|
aggregates by implementing the
|
|
<ulink url="../javadoc/org/apache/openjpa/jdbc/kernel/exps/JDBCAggregateListener.html">
|
|
<classname>org.apache.openjpa.jdbc.kernel.exps.JDBCAggregateListener</classname>
|
|
</ulink> interface. View the Javadoc documentation for details. When using your
|
|
custom aggregates in result or having query clauses, you can optionally prefix
|
|
the function name with <literal>ext:</literal> to identify it as an extension.
|
|
</para>
|
|
<section id="ref_guide_aggregates_conf">
|
|
<title>
|
|
Configuring Query Aggregates
|
|
</title>
|
|
<indexterm zone="ref_guide_aggregates_conf">
|
|
<primary>
|
|
JPQL
|
|
</primary>
|
|
<secondary>
|
|
aggregate extension
|
|
</secondary>
|
|
<tertiary>
|
|
configuration
|
|
</tertiary>
|
|
</indexterm>
|
|
<para>
|
|
There are two ways to register your custom query aggregates with OpenJPA:
|
|
</para>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>
|
|
<emphasis>Registration by properties:</emphasis> You can register custom query
|
|
aggregates by setting the <link linkend="openjpa.AggregateListeners"><literal>
|
|
openjpa.AggregateListeners</literal></link> configuration property to a
|
|
comma-separated list of plugin strings (see
|
|
<xref linkend="ref_guide_conf_plugins"/>) describing your aggregate
|
|
implementation. Aggregates registered in this fashion must have a public no-arg
|
|
constructor. They must also be thread safe, because they will be shared across
|
|
all queries.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<emphasis>Per-query registration:</emphasis> You can register query aggregates
|
|
for an individual <classname>Query</classname> through the <methodname>
|
|
OpenJPAQuery.addAggregateListener</methodname> method. You might use per-query
|
|
registration for very specific aggregates that do not apply globally.
|
|
</para>
|
|
<para>
|
|
See the <classname>OpenJPAQuery</classname>
|
|
<ulink url="../javadoc/org/apache/openjpa/persistence/OpenJPAQuery.html">
|
|
Javadoc</ulink> for details.
|
|
</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
</section>
|
|
-->
|
|
<section id="ref_guide_enterprise_methodql">
|
|
<title>
|
|
MethodQL
|
|
</title>
|
|
<indexterm zone="ref_guide_enterprise_methodql">
|
|
<primary>
|
|
MethodQL
|
|
</primary>
|
|
</indexterm>
|
|
<indexterm>
|
|
<primary>
|
|
Query
|
|
</primary>
|
|
<secondary>
|
|
MethodQL
|
|
</secondary>
|
|
<see>
|
|
MethodQL
|
|
</see>
|
|
</indexterm>
|
|
<para>
|
|
If JPQL and SQL queries do not match your needs, OpenJPA also allows you to name
|
|
a Java method to use to load a set of objects. In a <emphasis>MethodQL
|
|
</emphasis> query, the query string names a static method to invoke to determine
|
|
the matching objects:
|
|
</para>
|
|
<programlisting>
|
|
import org.apache.openjpa.persistence.*;
|
|
|
|
...
|
|
|
|
// the method query language is 'openjpa.MethodQL'.
|
|
// set the query string to the target method to execute, prefixed by fullly-
|
|
// qualified class name.
|
|
// If a candidate class has been specified for the query, then if the class is
|
|
// in the candidate class' package or in the query imports, you can omit the
|
|
// package. If the method is in the candidate class, you can omit the class name
|
|
// and just specify the method name.
|
|
|
|
OpenJPAEntityManager oem = OpenJPAPersistence.cast(emf);
|
|
OpenJPAQuery q = oem.createQuery("openjpa.MethodQL", "com.xyz.Finder.getByName");
|
|
|
|
// parameters are passed the same way as in standard queries
|
|
// but you have to declare the parameters with their types on the implementation
|
|
|
|
// Unwrap the implementation and declare parameters with types in a
|
|
// comma-separated list
|
|
q.unwrap(org.apache.openjpa.kernel.Query.class)
|
|
.declareParameters("String firstName, String lastName");
|
|
|
|
q.setParameter("firstName", "Fred").setParameter("lastName", "Lucas");
|
|
|
|
// this executes the target method to get the results
|
|
List results = q.getResultList();
|
|
|
|
// The result is returned as a list but the element(s) in the list is determined
|
|
// by the returned value of the target method
|
|
|
|
</programlisting>
|
|
<para>
|
|
For datastore queries, the method must have the following signature:
|
|
</para>
|
|
<programlisting>
|
|
public static <ulink url="../javadoc/org/apache/openjpa/lib/rop/ResultObjectProvider.html">ResultObjectProvider</ulink> xxx(<ulink url="../javadoc/org/apache/openjpa/kernel/StoreContext.html">StoreContext</ulink> ctx, <ulink url="../javadoc/org/apache/openjpa/meta/ClassMetaData.html">ClassMetaData</ulink> meta, boolean subclasses, Map params, <ulink url="../javadoc/org/apache/openjpa/kernel/FetchConfiguration.html">FetchConfiguration </ulink> fetch)
|
|
</programlisting>
|
|
<para>
|
|
The returned result object provider should produce objects of the candidate
|
|
class that match the method's search criteria. If the returned objects do not
|
|
have all fields in the given fetch configuration loaded, OpenJPA will make
|
|
additional trips to the datastore as necessary to fill in the data for the
|
|
missing fields.
|
|
</para>
|
|
<para>
|
|
In-memory execution is slightly different, taking in one object at a time and
|
|
returning a boolean on whether the object matches the query:
|
|
</para>
|
|
<programlisting>
|
|
public static boolean xxx(<ulink url="../javadoc/org/apache/openjpa/kernel/StoreContext.html">StoreContext</ulink> ctx, <ulink url="../javadoc/org/apache/openjpa/meta/ClassMetaData.html">ClassMetaData</ulink> meta, boolean subclasses, Object obj, Map params, <ulink url="../javadoc/org/apache/openjpa/kernel/FetchConfiguration.html">FetchConfiguration</ulink> fetch)
|
|
</programlisting>
|
|
<para>
|
|
In both method versions, the given <literal>params</literal> map contains the
|
|
names and values of all the parameters for the query.
|
|
</para>
|
|
</section>
|
|
<!--
|
|
</section>
|
|
-->
|
|
<section id="ref_guide_sequence">
|
|
<title>
|
|
Generators
|
|
</title>
|
|
<indexterm zone="ref_guide_sequence">
|
|
<primary>
|
|
generators
|
|
</primary>
|
|
<secondary>
|
|
Seq interface
|
|
</secondary>
|
|
</indexterm>
|
|
<para>
|
|
The JPA Overview's <xref linkend="jpa_overview_mapping"/> details using
|
|
generators to automatically populate identity fields in JPA.
|
|
</para>
|
|
<para>
|
|
OpenJPA represents all generators internally with the
|
|
<ulink url="../javadoc/org/apache/openjpa/kernel/Seq.html"><classname>
|
|
org.apache.openjpa.kernel.Seq</classname></ulink> interface. This interface
|
|
supplies all the context you need to create your own custom generators,
|
|
including the current persistence environment, the JDBC <classname>DataSource
|
|
</classname>, and other essentials. The
|
|
<ulink url="../javadoc/org/apache/openjpa/jdbc/kernel/AbstractJDBCSeq.html">
|
|
<classname>org.apache.openjpa.jdbc.kernel.AbstractJDBCSeq</classname></ulink>
|
|
helps you create custom JDBC-based sequences. OpenJPA also supplies the
|
|
following built-in <classname>Seq</classname>s:
|
|
</para>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>
|
|
<indexterm>
|
|
<primary>
|
|
generators
|
|
</primary>
|
|
<secondary>
|
|
table
|
|
</secondary>
|
|
</indexterm>
|
|
<literal>table</literal>: This is OpenJPA's default implementation. It is an
|
|
alias for the
|
|
<ulink url="../javadoc/org/apache/openjpa/jdbc/kernel/TableJDBCSeq.html">
|
|
<classname>org.apache.openjpa.jdbc.kernel.TableJDBCSeq</classname></ulink>
|
|
class. The <classname>TableJDBCSeq</classname> uses a special single-row table
|
|
to store a global sequence number. If the table does not already exist, it is
|
|
created the first time you run the
|
|
<link linkend="ref_guide_mapping_mappingtool">mapping tool</link> on a class
|
|
that requires it. You can also use the class's <methodname>main</methodname>
|
|
method to manipulate the table; see the
|
|
<methodname>TableJDBCSeq.main</methodname> method Javadoc for usage details.
|
|
</para>
|
|
<para>
|
|
This <classname>Seq</classname> has the following properties:
|
|
</para>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>
|
|
<literal>Table</literal>: The name of the sequence number table to use.
|
|
Defaults to <literal>OPENJPA_SEQUENCE_TABLE</literal>. If the entities are
|
|
mapped to the same table name but with different schema name within one
|
|
PersistenceUnit, one <literal>OPENJPA_SEQUENCE_TABLE</literal> is created
|
|
for each schema.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<literal>PrimaryKeyColumn</literal>: The name of the primary key column for the
|
|
sequence table. Defaults to <literal>ID</literal>.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<literal>SequenceColumn</literal>: The name of the column that will hold the
|
|
current sequence value. Defaults to <literal>SEQUENCE_VALUE</literal>.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<literal>Allocate</literal>: The number of values to allocate on each database
|
|
trip. Defaults to 50, meaning the class will set aside the next 50 numbers each
|
|
time it accesses the sequence table, which in turn means it only has to make a
|
|
database trip to get new sequence numbers once every 50 sequence number
|
|
requests.
|
|
</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<indexterm>
|
|
<primary>
|
|
generators
|
|
</primary>
|
|
<secondary>
|
|
class-table
|
|
</secondary>
|
|
</indexterm>
|
|
<literal>class-table</literal>: This is an alias for the
|
|
<ulink url="../javadoc/org/apache/openjpa/jdbc/kernel/ClassTableJDBCSeq.html">
|
|
<classname>org.apache.openjpa.jdbc.kernel.ClassTableJDBCSeq</classname></ulink>
|
|
. This <classname>Seq</classname> is like the <classname>TableJDBCSeq
|
|
</classname> above, but maintains a separate table row, and therefore a separate
|
|
sequence number, for each base persistent class. It has all the properties of
|
|
the <classname>TableJDBCSeq</classname>. Its table name defaults to <literal>
|
|
OPENJPA_SEQUENCES_TABLE</literal>. It also adds the following properties:
|
|
</para>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>
|
|
<literal>IgnoreUnmapped</literal>: Whether to ignore unmapped base classes, and
|
|
instead use one row per least-derived mapped class. Defaults to <literal>
|
|
false</literal>.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<literal>UseAliases</literal>: Whether to use each class' entity name as the
|
|
primary key value of each row, rather than the full class name. Defaults to
|
|
<literal>false</literal>.
|
|
</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
<para>
|
|
As with the <classname>TableJDBCSeq</classname>, the <classname>
|
|
ClassTableJDBCSeq</classname> creates its table automatically during mapping
|
|
tool runs. However, you can manually manipulate the table through the class'
|
|
<methodname>main</methodname> method. See the Javadoc for the
|
|
<methodname> ClassTableJDBCSeq.main</methodname> method for usage details.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<indexterm>
|
|
<primary>
|
|
generators
|
|
</primary>
|
|
<secondary>
|
|
value-table
|
|
</secondary>
|
|
</indexterm>
|
|
<literal>value-table</literal>: This is an alias for the
|
|
<ulink url="../javadoc/org/apache/openjpa/jdbc/kernel/ValueTableJDBCSeq.html">
|
|
<classname>org.apache.openjpa.jdbc.kernel.ValueTableJDBCSeq</classname></ulink>
|
|
. This <classname>Seq</classname> is like the <classname>ClassTableJDBCSeq
|
|
</classname> above, but has an arbitrary number of rows for sequence values,
|
|
rather than a fixed pattern of one row per class. Its table defaults to
|
|
<literal>OPENJPA_SEQUENCES_TABLE</literal>. It has all the properties of the
|
|
<classname>TableJDBCSeq</classname>, plus:
|
|
</para>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>
|
|
<literal>PrimaryKeyValue</literal>: The primary key value used by this instance.
|
|
</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
<para>
|
|
As with the <classname>TableJDBCSeq</classname>, the <classname>
|
|
ValueTableJDBCSeq</classname> creates its table automatically during mapping
|
|
tool runs. However, you can manually manipulate the table through the class'
|
|
<methodname>main</methodname> method. See the Javadoc for the
|
|
<methodname>ValueTableJDBCSeq.main</methodname> method for usage details.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<indexterm>
|
|
<primary>
|
|
generators
|
|
</primary>
|
|
<secondary>
|
|
native
|
|
</secondary>
|
|
</indexterm>
|
|
<literal>native</literal>: This is an alias for the
|
|
<ulink url="../javadoc/org/apache/openjpa/jdbc/kernel/NativeJDBCSeq.html">
|
|
<classname>org.apache.openjpa.jdbc.kernel.NativeJDBCSeq</classname></ulink>.
|
|
Many databases have a concept of "native sequences" - a built-in mechanism for
|
|
obtaining incrementing numbers. For example, in Oracle, you can create a
|
|
database sequence with a statement like <literal>CREATE SEQUENCE MYSEQUENCE
|
|
</literal>. Sequence values can then be atomically obtained and incremented
|
|
with the statement <literal>SELECT MYSEQUENCE.NEXTVAL FROM DUAL</literal>.
|
|
OpenJPA provides support for this common mechanism of sequence generation with
|
|
the <classname> NativeJDBCSeq</classname>, which accepts the following
|
|
properties:
|
|
</para>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>
|
|
<literal>Sequence</literal>: The name of the database sequence. Defaults to
|
|
<literal>OPENJPA_SEQUENCE</literal>.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<literal>InitialValue</literal>: The initial sequence value. Defaults to 1.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<literal>Increment</literal>: The amount the sequence increments. Defaults to 1.
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<literal>Allocate</literal>: Some database can allocate values in-memory to
|
|
service subsequent sequence requests faster.
|
|
</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<indexterm>
|
|
<primary>
|
|
generators
|
|
</primary>
|
|
<secondary>
|
|
time
|
|
</secondary>
|
|
</indexterm>
|
|
<literal>time</literal>: This is an alias for the
|
|
<ulink url="../javadoc/org/apache/openjpa/kernel/TimeSeededSeq.html">
|
|
<classname>org.apache.openjpa.kernel.TimeSeededSeq</classname></ulink>. This
|
|
type uses an in-memory static counter, initialized to the current time in
|
|
milliseconds and monotonically incremented for each value requested. It is only
|
|
suitable for single-JVM environments.
|
|
</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
<para>
|
|
You can use JPA <literal>SequenceGenerator</literal>s to describe any built-in
|
|
<classname>Seq</classname>s or your own <classname>Seq</classname>
|
|
implementation. Set the <literal>sequenceName</literal> attribute to a plugin
|
|
string describing your choice.
|
|
</para>
|
|
|
|
<blockquote>
|
|
<para>
|
|
If specifying your own class name, you must include parentheses at the end of
|
|
the class name, even if you have no plugin properties to configure.
|
|
(E.g., <literal>sequenceName="com.example.SeqImpl()"</literal>.
|
|
</para>
|
|
</blockquote>
|
|
|
|
<para>
|
|
See <xref linkend="jpa_overview_mapping_sequence"/> in the JPA Overview for
|
|
details on defining <literal>SequenceGenerator</literal>s.
|
|
</para>
|
|
|
|
<para>
|
|
See <xref linkend="ref_guide_conf_plugins"/> for plugin string formatting.
|
|
</para>
|
|
<example id="ref_guide_sequence_named">
|
|
<title>
|
|
Named Seq Sequence
|
|
</title>
|
|
<programlisting>
|
|
@Entity
|
|
@Table(name="AUTO")
|
|
public class Author {
|
|
|
|
@Id
|
|
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="AuthorSeq")
|
|
@SequenceGenerator(name="AuthorSeq", sequenceName="table(Table=AUTO_SEQ)", allocationSize=100)
|
|
@Column(name="AID")
|
|
private long id;
|
|
|
|
...
|
|
}
|
|
</programlisting>
|
|
<para>
|
|
Note that if you want to use a plugin string without any arguments, you must
|
|
still suffix the plugin type with <literal>()</literal> to differentiate it from
|
|
a sequence name in the <literal>SequenceGenerator.sequenceName</literal> attribute:
|
|
</para>
|
|
<programlisting>
|
|
@SequenceGenerator(name="AuthorSeq", sequenceName="table()")
|
|
</programlisting>
|
|
</example>
|
|
<para>
|
|
OpenJPA maintains a <emphasis>system</emphasis> sequence to generate datastore
|
|
identity values for classes that do not declare a specific datastore identity
|
|
strategy. You can configure the system sequence through the
|
|
<link linkend="openjpa.Sequence"><literal>openjpa.Sequence</literal></link>
|
|
configuration property. This property accepts a plugin string describing a
|
|
<classname>Seq</classname> instance.
|
|
</para>
|
|
<example id="ref_guide_sequence_systemex">
|
|
<title>
|
|
System Sequence Configuration
|
|
</title>
|
|
<programlisting>
|
|
<property name="openjpa.Sequence" value="table(Table=OPENJPASEQ, Increment=100)"/>
|
|
</programlisting>
|
|
</example>
|
|
<para>
|
|
In JPA, set your <literal>GeneratedValue</literal> annotation's <literal>
|
|
strategy</literal> attribute to <literal>AUTO</literal> to use the configured
|
|
system sequence. Or, because <literal>AUTO</literal> is the default strategy,
|
|
use the annotation without attributes:
|
|
</para>
|
|
<programlisting>
|
|
@GeneratedValue
|
|
private long id;
|
|
</programlisting>
|
|
<section id="ref_guide_sequence_runtime">
|
|
<title>
|
|
Runtime Access
|
|
</title>
|
|
<indexterm zone="ref_guide_sequence_runtime">
|
|
<primary>
|
|
Sequence
|
|
</primary>
|
|
<secondary>
|
|
runtime access
|
|
</secondary>
|
|
</indexterm>
|
|
<para>
|
|
OpenJPA allows you to access named generators at runtime through the
|
|
<methodname>OpenJPAEntityManager.getNamedGenerator</methodname> method:
|
|
</para>
|
|
<programlisting>
|
|
public Generator getNamedGenerator(String name);
|
|
</programlisting>
|
|
<para>
|
|
The returned
|
|
<ulink url="../javadoc/org/apache/openjpa/persistence/Generator.html">
|
|
<classname>org.apache.openjpa.persistence.Generator</classname></ulink> is a
|
|
facade over an internal OpenJPA <classname>Seq</classname>.
|
|
</para>
|
|
<para>
|
|
The <classname>OpenJPAEntityManager</classname> includes additional APIs to
|
|
retrieve the identity generator of any class, or the generator of any field.
|
|
With these APIs, you do not have to know the generator name. Additionally, they
|
|
allow you to access the implicit generator used by default for datastore
|
|
identity classes. See the
|
|
<ulink url="../javadoc/org/apache/openjpa/persistence/OpenJPAEntityManager.html">
|
|
Javadoc</ulink> for the <methodname> OpenJPAEntityManager.getIdentityGenerator
|
|
</methodname> and <methodname>OpenJPAEntityManager.getFieldGenerator
|
|
</methodname> methods for API details.
|
|
</para>
|
|
</section>
|
|
</section>
|
|
<section id="ref_guide_runtime_pm_event">
|
|
<title>
|
|
Transaction Events
|
|
</title>
|
|
<indexterm zone="ref_guide_runtime_pm_event">
|
|
<primary>
|
|
transactions
|
|
</primary>
|
|
<secondary>
|
|
events
|
|
</secondary>
|
|
</indexterm>
|
|
<para>
|
|
The OpenJPA runtime supports broadcasting transaction-related events. By
|
|
registering one or more
|
|
<ulink url="../javadoc/org/apache/openjpa/event/TransactionListener.html">
|
|
<classname>org.apache.openjpa.event.TransactionListener</classname></ulink> s,
|
|
you can receive notifications when transactions begin, flush, rollback, commit,
|
|
and more. Where appropriate, event notifications include the set of
|
|
persistence-capable objects participating in the transaction.
|
|
</para>
|
|
<programlisting>
|
|
public void addTransactionListener(Object listener);
|
|
public void removeTransactionListener(Object listener);
|
|
</programlisting>
|
|
<para>
|
|
These <classname>OpenJPAEntityManagerSPI</classname> methods allow you to add
|
|
and remove listeners. These methods are outside the bounds of the published OpenJPA APIs, and are subject to change in the future.
|
|
</para>
|
|
<para>
|
|
For details on the transaction framework, see the <literal>
|
|
org.apache.openjpa.event</literal> package
|
|
<ulink url="../javadoc/org/apache/openjpa/event/package.html">Javadoc</ulink>.
|
|
Also see <xref linkend="ref_guide_event"/> for a description of OpenJPA's
|
|
remote event support.
|
|
</para>
|
|
</section>
|
|
<section id="ref_guide_enterprise_abstractstore">
|
|
<title>
|
|
Non-Relational Stores
|
|
</title>
|
|
<para>
|
|
It is possible to adapt OpenJPA to access a non-relational datastore by creating
|
|
an implementation of the
|
|
<ulink url="../javadoc/org/apache/openjpa/kernel/StoreManager.html"><literal>
|
|
org.apache.openjpa.kernel.StoreManager</literal></ulink> interface. OpenJPA
|
|
provides an abstract <literal>StoreManager</literal> implementation to
|
|
facilitate this process. See the <literal>org.apache.openjpa.abstractstore
|
|
</literal> package <ulink url="../javadoc/org/apache/openjpa/abstractstore">
|
|
Javadoc</ulink> for details.
|
|
</para>
|
|
</section>
|
|
</chapter>
|