You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by mp...@apache.org on 2006/08/22 23:28:55 UTC
svn commit: r433761 [17/18] - in /incubator/openjpa/trunk/openjpa-project:
./ src/doc/manual/
Added: incubator/openjpa/trunk/openjpa-project/src/doc/manual/ref_guide_runtime.xml
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-project/src/doc/manual/ref_guide_runtime.xml?rev=433761&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-project/src/doc/manual/ref_guide_runtime.xml (added)
+++ incubator/openjpa/trunk/openjpa-project/src/doc/manual/ref_guide_runtime.xml Tue Aug 22 14:28:53 2006
@@ -0,0 +1,1441 @@
+
+ <chapter id="ref_guide_runtime">
+ <title>Runtime Extensions</title>
+ <para>
+ This chapter describes OpenJPA extensions to the standard
+ <phrase>JPA</phrase>
+
+
+ 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 can
+ OpenJPA's native kernel can adopt.
+ </para>
+ <para>
+ As a OpenJPA <phrase>JPA</phrase> 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_pmextension">
+ <title>Broker Customization</title>
+ <indexterm zone="ref_guide_runtime_pmextension">
+ <primary>OpenJPAEntityManager</primary>
+ <secondary>extending</secondary>
+ </indexterm>
+ <para>
+ Some advanced users may want to add capabilities to OpenJPA's internal
+ <ulink url="../apidocs/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> through the
+ <link linkend="openjpa.BrokerImpl"><literal>openjpa.BrokerImpl</literal></link> configuration property. Set this property to the full
+ class name of your custom subclass.
+ </para>
+ <para>
+ As a <link linkend="ref_guide_conf_plugins">plugin string</link>,
+ you can also use this property 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 format="linespecific">
+<property name="openjpa.BrokerImpl" value="EvictFromDataCache=true"/>
+</programlisting>
+ </example>
+ </section>
+ </section>
+ <section id="ref_guide_runtime_ejb">
+ <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 JDO 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 format="linespecific">
+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 obtain
+ managed and unmanaged <classname>EntityManager</classname>s from
+ the same factory, to access the OpenJPA data and query caches, and to
+ perform other OpenJPA-specific operations. See the
+ <ulink url="../../api/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="../../api/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_ejbquery">
+ <title>OpenJPAQuery</title>
+ <indexterm zone="ref_guide_runtime_ejbquery">
+ <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="../../api/openjpa/persistence/OpenJPAQuery.html">Javadoc
+ </ulink> for details on the convenience methods it provides.
+ </para>
+ </section>
+ <section id="ref_guide_runtime_ejbextent">
+ <title>Extent</title>
+ <indexterm zone="ref_guide_runtime_ejbextent">
+ <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="../../api/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_ejbextentex">
+ <title>Using a JPA Extent</title>
+ <programlisting format="linespecific">
+import org.apache.openjpa.persistence.*;
+
+...
+
+OpenJPAEntityManager kem = OpenJPAPersistence.cast (em);
+Extent<Magazine> mags = kem.getExtent (Magazine.class, false);
+for (Magazine m : mags)
+ processMagazine (m);
+</programlisting>
+ </example>
+ </section>
+ <section id="ref_guide_runtime_ejbcache">
+ <title>StoreCache</title>
+ <indexterm zone="ref_guide_runtime_ejbcache">
+ <primary>StoreCache</primary>
+ </indexterm>
+ <para>
+ In addition to the <classname>EntityManager</classname> object
+ cache mandated by the JPA specification, OpenJPA includes
+ a flexible datastore-level cache. You can access this cache
+ from your JPA code using the
+ <ulink url="../../api/openjpa/persistence/StoreCache.html"><classname>
+ org.apache.openjpa.persistence.StoreCache</classname></ulink> facade.
+ <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_ejbquerycache">
+ <title>QueryResultCache</title>
+ <indexterm zone="ref_guide_runtime_ejbquerycache">
+ <primary>QueryResultCache</primary>
+ </indexterm>
+ <para>
+ OpenJPA can cache query results as well as persistent object data. The
+ <ulink url="../../api/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_ejbfetch">
+ <title>FetchPlan</title>
+ <indexterm zone="ref_guide_runtime_ejbfetch">
+ <primary>FetchPlan</primary>
+ </indexterm>
+ <indexterm>
+ <primary>eager fetching</primary>
+ <seealso>FetchPlan</seealso>
+ </indexterm>
+ <para>
+ Many of the aforementioned OpenJPA interfaces give you access to a
+ <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="../../api/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_openjpapersistence">
+ <title>OpenJPAPersistence</title>
+ <indexterm zone="ref_guide_runtime_openjpapersistence">
+ <primary>OpenJPAPersistence</primary>
+ </indexterm>
+ <para><ulink url="../../api/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>, 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 format="linespecific">
+<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 format="linespecific">
+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 format="linespecific">
+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 kq = OpenJPAPersistence.cast (q);
+FetchPlan fetch = kq.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 format="linespecific">
+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/5/docs/api/javax/persistence/EntityManager.html"><methodname>EntityManager.lock (Object, LockModeType)</methodname></ulink> method, the
+ <ulink url="../../api/openjpa/persistence/OpenJPAEntityManager.html"><classname>OpenJPAEntityManager</classname></ulink> exposes the following
+ methods to lock objects explicitly:
+ </para>
+ <programlisting format="linespecific">
+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 format="linespecific">
+import org.apache.openjpa.persistence.*;
+
+// retrieve the lock level of an object
+OpenJPAEntityManager kem = OpenJPAPersistence.cast (em);
+Stock stock = ...;
+LockModeType level = kem.getLockMode (stock);
+if (level == OpenJPAModeType.WRITE) ...
+
+...
+
+kem.setOptimistic (true);
+kem.getTransaction ().begin ();
+
+// override default of not locking during an opt trans to lock stock object
+kem.lock (stock, LockModeType.WRITE, 1000);
+stock.setPrice (market.calculatePrice (stock));
+
+kem.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="../apidocs/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>pessimistic</literal>: This is an alias for the
+ <ulink url="../apidocs/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
+ configued 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 format="linespecific">
+<property name="openjpa.LockManager" value="pessimistic(VersionCheckOnReadLock=true,VersionUpdateOnWriteLock=true)"/>
+</programlisting>
+ </listitem>
+ <listitem>
+ <para><literal>none</literal>: An alias for the
+ <ulink url="../apidocs/org/apache/openjpa/kernel/NoneLockManager.html"><classname>org.apache.openjpa.kernel.NoneLockManager</classname></ulink>,
+ which does not perform any locking at all.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>sjvm</literal>: An alias for the
+ <ulink url="../apidocs/org/apache/openjpa/kernel/SingleJVMExclusiveLockManager.html"><classname>org.apache.openjpa.kernel.SingleJVMExclusiveLockManager
+ </classname></ulink>. This lock manager uses in-memory mutexes
+ to obtain exclusive locks on object ids. It does not perform
+ any database-level locking. Also, it does not distinguish
+ between read and write locks; all locks are write locks.
+ </para>
+ </listitem>
+ <listitem>
+ <para><literal>version</literal>: An alias for the
+ <ulink url="../apidocs/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>
+ <para>
+ This is the default <literal>openjpa.LockManager</literal>
+ setting in JPA.
+ </para>
+ </listitem>
+ </itemizedlist>
+ <note>
+ <para>
+ In order for the <literal>version</literal> lock manager
+ 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 format="linespecific">
+<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 default lock manager, however, OpenJPA must begin a
+ database transaction whenever you decide to lock an object
+ during an optimistic transaction. This is because the
+ default 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 default 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 default 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 flexibilty
+ 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
+ <phrase><ulink url="../../api/openjpa/persistence/OpenJPAEntityManager.html"><classname>OpenJPAEntityManager</classname></ulink></phrase>
+
+
+ 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 format="linespecific">
+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
+ such as in memory state and datastore 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 format="linespecific">
+import org.apache.openjpa.persistence.*;
+
+...
+
+OpenJPAEntityManager kem = OpenJPAPersistence.cast (em);
+kem.getTransaction ().begin ();
+
+Magazine mag = kem.find (Magazine.class, id);
+mag.setPageCount (300);
+kem.setSavepoint ("pages");
+
+mag.setPrice (mag.getPageCount () * pricePerPage);
+// we decide to release pages since price depends on pages.
+kem.releaseSavepoint ("pages");
+kem.setSavepoint ("price");
+
+mag.setPrice (testPrice);
+...
+
+// we determine the test price is not good
+kem.rollbackToSavepoint ("price");
+
+// the price is now restored to mag.getPageCount () * pricePerPage
+kem.getTransaction ().commit ();
+</programlisting>
+ </example>
+ </section>
+ <section id="ref_guide_savepoints_conf">
+ <title>Configuring Savepoints</title>
+ <para>
+ OpenJPA uses the <ulink url="javadoc/openjpa/kernel/SavepointManager"><classname>org.apache.openjpa.kernel.SavepointManager</classname></ulink>
+ <link linkend="ref_guide_conf_plugins">plugin</link> to handle
+ perserving 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>
+<!-- ### EJBDOC : remove note when parser upgraded -->
+ <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 format="linespecific">
+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 format="linespecific">
+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 format="linespecific">
+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 format="linespecific">
+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="../apidocs/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="../../api/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="../apidocs/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="../../api/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 format="linespecific">
+import org.apache.openjpa.persistence.*;
+
+...
+
+// the method query language is 'openjpa.MethodQL'.
+// set the query string to the method to execute, including full class name; 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 kem = OpenJPAPersistence.cast (emf);
+OpenJPAQuery q = kem.createQuery ("openjpa.MethodQL", "com.xyz.Finder.getByName");
+
+// set the type of objects that the method returns
+q.setResultClass (Person.class);
+
+// parameters are passed the same way as in standard queries
+q.setParameter ("firstName", "Fred").setParameter ("lastName", "Lucas");
+
+// this executes your method to get the results
+List results = q.getResultList ();
+</programlisting>
+ <para>
+ For datastore queries, the method must have the following signature:
+ </para>
+ <programlisting format="linespecific">
+public static <ulink url="../apidocs/org/apache/openjpa/lib/rop/ResultObjectProvider.html">ResultObjectProvider</ulink> xxx(<ulink url="../apidocs/org/apache/openjpa/kernel/StoreContext.html">StoreContext</ulink> ctx,
+ <ulink url="../apidocs/org/apache/openjpa/meta/ClassMetaData.html">ClassMetaData</ulink> meta, boolean subclasses, Map params, <ulink url="../apidocs/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 format="linespecific">
+public static boolean xxx(<ulink url="../apidocs/org/apache/openjpa/kernel/StoreContext.html">StoreContext</ulink> ctx, <ulink url="../apidocs/org/apache/openjpa/meta/ClassMetaData.html">ClassMetaData</ulink> meta,
+ boolean subclasses, Object obj, Map params, <ulink url="../apidocs/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="../apidocs/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="../apidocs/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="../apidocs/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>'s on a class that requires it. You can also
+ use the class' <methodname>main</methodname> method or the
+ <literal>sequencetable</literal> shell/bat script 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>.
+ </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="../apidocs/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, or through the <literal>classsequencetable</literal>
+ shell/bat script. 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="../apidocs/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, or through the <literal>valuesequencetable</literal>
+ shell/bat script. 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="../apidocs/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="../apidocs/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. 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 format="linespecific">
+@Entity
+@Table(name="AUTO")
+public class Author
+{
+ @Id
+ @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="AuthorSeq")
+ @SequenceGenerator(name="AuthorSeq" sequence="table(Table=AUTO_SEQ, Increment=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.sequence</literal> attribute:
+ </para>
+ <programlisting format="linespecific">
+@SequenceGenerator(name="AuthorSeq", sequence="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 format="linespecific">
+<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 format="linespecific">
+@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 format="linespecific">
+public Generator getNamedGenerator (String name);
+</programlisting>
+ <para>
+ The returned <ulink url="../../api/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="../../api/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="../apidocs/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 format="linespecific">
+public void addTransactionListener (Object listener);
+public void removeTransactionListener (Object listener);
+</programlisting>
+ <para>
+ These <classname>OpenJPAEntityManager</classname> methods allow you
+ to add and remove listeners.
+ </para>
+ <para>
+ For details on the transaction framework, see the <literal>
+ org.apache.openjpa.event</literal> package
+ <ulink url="../apidocs/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="../apidocs/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="../apidocs/org/apache/openjpa/abstractstore">Javadoc</ulink> for
+ details.
+
+ </para>
+ </section>
+ </chapter>
Added: incubator/openjpa/trunk/openjpa-project/src/doc/manual/samples_guide.xml
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-project/src/doc/manual/samples_guide.xml?rev=433761&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-project/src/doc/manual/samples_guide.xml (added)
+++ incubator/openjpa/trunk/openjpa-project/src/doc/manual/samples_guide.xml Tue Aug 22 14:28:53 2006
@@ -0,0 +1,137 @@
+
+ <chapter id="samples_guide">
+ <title>OpenJPA Sample Code</title>
+ <para>
+ The OpenJPA distribution comes with a number of examples that
+ illustrate the usage of various features.
+ </para>
+<!--
+ This is information on the sample application. It will be included
+ in the documentation (see doc/openjpa/samples-guide.xml). It will also
+ automatically be converted into a README.txt file in this directory
+ in the "release.org.apache.openjpa.releasedocs" build target phase of the release.
+-->
+ <section id="samples_guide_interop">
+ <title>JDO - JPA Persistence Interoperability</title>
+ <para>This sample demonstrates how to combine JDO and JPA in a single
+application. The <filename>MachineMain.java</filename> program uses both
+<classname>EntityManager</classname>s and <classname>PersistenceManager</classname>s
+in a single transaction including persist, delete and query operations.</para>
+ <para>The sample includes both annotated persistent classes as well as JDOR
+metadata information. The application can switch to either system simply
+by changing the bootstrap mechanism. Depending on which configuration
+system you use, OpenJPA will read the corresponding metadata format. You can
+override some or all of this behavior using OpenJPA's configuration options,
+such as <link linkend="openjpa.MetaDataFactory">openjpa.MetaDataFactory</link>.</para>
+ <para>To use this sample, you should ensure that either a <filename>jdo.properties</filename>
+or <filename>persistence.xml</filename> are in the <filename>META-INF</filename> directory
+in your <envar>CLASSPATH</envar>. The rest of the files for this sample are located in the
+<filename>samples/mixed</filename> directory of the OpenJPA installation. This tutorial requires JDK 5.
+To run this tutorial:</para>
+ <itemizedlist>
+ <listitem>
+ <para>Ensure that your environment is set properly as described in the
+ README and that your current path is in the mixed sample directory.</para>
+ </listitem>
+ <listitem>
+ <para>
+ You may want to edit <literal>ConnectionURL</literal> to point to an absolute
+ URL (e.g. <filename>C:/openjpa/mixed-sample-db</filename>) if using a file-based database like
+ <literal>HSQL</literal>.</para>
+ </listitem>
+ <listitem>
+ <para>Include the list of persistent classes in your configuration file. For
+ JPA, you will want to add the following lines to
+ <filename>persistence.xml</filename> before the <literal><property></literal> lines:
+ </para>
+ <programlisting format="linespecific">
+<class>samples.mixed.Machine</class>
+<class>samples.mixed.Crane</class>
+<class>samples.mixed.Bulldozer</class>
+<class>samples.mixed.Operator</class>
+</programlisting>
+ <para>
+ If you are using JDO, point the metadata factory at the <filename>.jdo</filename>
+resource containing your persistent classes:
+ </para>
+ <programlisting format="linespecific">
+openjpa.MetaDataFactory: Resources=samples/mixed/package.jdo
+</programlisting>
+ </listitem>
+ <listitem>
+ <para>Compile the classes:
+
+ </para>
+ <para>
+ <userinput>javac *.java</userinput>
+ </para>
+ </listitem>
+ <listitem>
+ <para>You should then proceed to pass in the configuration file you are using
+ to the enhancer:
+
+ </para>
+ <para>
+ <userinput>openjpac -p persistence.xml Machine.java Crane.java Bulldozer.java Operator.java</userinput>
+ </para>
+ <para>
+ or
+ </para>
+ <para>
+ <userinput>jdoc -p jdo.properties Machine.java Crane.java Bulldozer.java Operator.java</userinput>
+ </para>
+ </listitem>
+ <listitem>
+ <para>Similarly, you should pass in the same argument to <literal>mappingtool</literal>:
+
+ </para>
+ <para>
+ <userinput>mappingtool -p persistence.xml -a buildSchema Machine.java Crane.java Bulldozer.java Operator.java</userinput>
+ </para>
+ <para>
+ or
+ </para>
+ <para>
+ <userinput>mappingtool -p jdo.properties -a buildSchema Machine.java Crane.java Bulldozer.java Operator.java</userinput>
+ </para>
+ </listitem>
+ <listitem>
+ <para>You can now run the sample application. The first argument is
+ which operation you want the program to run. The second argument tells
+ the application which bootstrap system to use:
+
+ </para>
+ <para>
+ <userinput>java samples.mixed.MachineMain <create | delete> <jdo | jpa></userinput>
+ </para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ <section id="samples_guide_ejbdiv">
+ <title>JPA</title>
+<!--
+ This is information on the sample application. It will be included
+ in the documentation (see doc/openjpa/samples-guide.xml). It will also
+ automatically be converted into a README.txt file in this directory
+ in the "release.jdo.releasedocs" build target phase of the release.
+-->
+ <section id="samples_guide_model_humres_ejb">
+ <title>Sample Human Resources Model</title>
+ <para>The files for this sample are located in the <filename>samples/persistence/models/humres</filename>
+directory of the OpenJPA installation. This sample demonstrates the mapping of
+an example "Human Resources" schema. The following concepts are illustrated
+in this sample:</para>
+ <itemizedlist>
+ <listitem>
+ <para>Value Mappings</para>
+ </listitem>
+ <listitem>
+ <para>One to One Mappings</para>
+ </listitem>
+ <listitem>
+ <para>One to Many Mappings (with and without inverses)</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+ </section>
+ </chapter>