blob: 13338a425ca869ba0b8f8bce7357b9ce964f2586 [file] [log] [blame]
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>4.&nbsp; Object Identity</title><link rel="stylesheet" href="css/docbook.css" type="text/css"><base href="display"><meta name="generator" content="DocBook XSL Stylesheets V1.72.0"><link rel="start" href="manual.html" title="Apache OpenJPA 2.1 User's Guide"><link rel="up" href="ref_guide_pc.html" title="Chapter&nbsp;5.&nbsp; Persistent Classes"><link rel="prev" href="ref_guide_pc_interfaces.html" title="3.&nbsp;Managed Interfaces"><link rel="next" href="ref_guide_inverses.html" title="5.&nbsp; Managed Inverses"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">4.&nbsp;
Object Identity
</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="ref_guide_pc_interfaces.html">Prev</a>&nbsp;</td><th width="60%" align="center">Chapter&nbsp;5.&nbsp;
Persistent Classes
</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="ref_guide_inverses.html">Next</a></td></tr></table><hr></div><div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="ref_guide_pc_oid"></a>4.&nbsp;
Object Identity
</h2></div></div></div><div class="toc"><dl><dt><span class="section"><a href="ref_guide_pc_oid.html#ref_guide_pc_oid_datastore">4.1.
Datastore Identity
</a></span></dt><dt><span class="section"><a href="ref_guide_pc_oid.html#ref_guide_pc_oid_entitypk">4.2.
Entities as Identity Fields
</a></span></dt><dt><span class="section"><a href="ref_guide_pc_oid.html#ref_guide_pc_oid_application">4.3.
Application Identity Tool
</a></span></dt><dt><span class="section"><a href="ref_guide_pc_oid.html#ref_guide_pc_oid_pkgen_autoinc">4.4.
Autoassign / Identity Strategy Caveats
</a></span></dt></dl></div><a class="indexterm" name="d0e25607"></a><p>
OpenJPA makes several enhancements to JPA's standard entity identity.
</p><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="ref_guide_pc_oid_datastore"></a>4.1.&nbsp;
Datastore Identity
</h3></div></div></div><a class="indexterm" name="d0e25615"></a><p>
The JPA specification requires you to declare one or more identity fields in
your persistent classes. OpenJPA fully supports this form of object identity,
called <span class="emphasis"><em>application</em></span> identity. OpenJPA, however, also
supports <span class="emphasis"><em>datastore</em></span> identity. In datastore identity, you do
not declare any primary key fields. OpenJPA manages the identity of your
persistent objects for you through a surrogate key in the database.
</p><p>
You can control how your JPA datastore identity value is generated through
OpenJPA's
<a xmlns:xlink="http://www.w3.org/1999/xlink" href="../javadoc/org/apache/openjpa/persistence/DataStoreId.html" target="_top">
<code class="classname">org.apache.openjpa.persistence.DataStoreId</code></a> class
annotation. This annotation has <code class="literal">strategy</code> and <code class="literal">
generator</code> properties that mirror the same-named properties on the
standard <code class="classname">javax.persistence.GeneratedValue</code> annotation
described in <a href="jpa_overview_meta_field.html#jpa_overview_meta_id" title="2.3.&nbsp; Id">Section&nbsp;2.3, &#8220;
Id
&#8221;</a> of the JPA Overview.
</p><p>
To retrieve the identity value of a datastore identity entity, use the
<code class="methodname">OpenJPAEntityManager.getObjectId(Object entity)</code>
method. See <a href="ref_guide_runtime_jpa.html#ref_guide_runtime_em" title="2.2.&nbsp; OpenJPAEntityManager">Section&nbsp;2.2, &#8220;
OpenJPAEntityManager
&#8221;</a> for more information on
the <code class="classname">OpenJPAEntityManager</code>.
</p><div class="example"><a name="ref_guide_pc_oid_datastoreentityex"></a><p class="title"><b>Example&nbsp;5.4.&nbsp;
JPA Datastore Identity Metadata
</b></p><div class="example-contents"><pre class="programlisting">
import org.apache.openjpa.persistence.*;
@Entity
@DataStoreId
public class LineItem {
... no @Id fields declared ...
}
</pre></div></div><br class="example-break"><p>
Internally, OpenJPA uses the public
<a xmlns:xlink="http://www.w3.org/1999/xlink" href="../javadoc/org/apache/openjpa/util/Id.html" target="_top"><code class="classname">
org.apache.openjpa.util.Id</code></a> class for datastore identity
objects. When writing OpenJPA plugins, you can manipulate datastore identity
objects by casting them to this class. You can also create your own <code class="classname">
Id</code> instances and pass them to any internal OpenJPA method that
expects an identity object.
</p><p>
In JPA, you will never see <code class="classname">Id</code> instances directly.
Instead, calling <code class="classname">OpenJPAEntityManager.getObjectId</code> on a
datastore identity object will return the <code class="classname">Long</code> surrogate
primary key value for that object. You can then use this value in calls to
<code class="classname">EntityManager.find</code> for subsequent lookups of the same
record.
</p></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="ref_guide_pc_oid_entitypk"></a>4.2.&nbsp;
Entities as Identity Fields
</h3></div></div></div><a class="indexterm" name="d0e25687"></a><p>
OpenJPA allows <code class="literal">ManyToOne</code> and <code class="literal">OneToOne</code>
relations to be identity fields. To identify a relation field as an identity
field, simply annotate it with both the <code class="literal">@ManyToOne</code> or
<code class="literal">@OneToOne</code> relation annotation and the <code class="literal">@Id</code>
identity annotation.
</p><p>
When finding an entity identified by a relation, pass the id of the
<span class="emphasis"><em>relation</em></span> to the <code class="methodname">EntityManager.find</code>
method:
</p><div class="example"><a name="ref_guide_pc_oid_entitypk_simplefind"></a><p class="title"><b>Example&nbsp;5.5.&nbsp;
Finding an Entity with an Entity Identity Field
</b></p><div class="example-contents"><pre class="programlisting">
public Delivery createDelivery(Order order) {
Delivery delivery = new Delivery();
delivery.setId(order);
delivery.setDelivered(new Date());
return delivery;
}
public Delivery findDelivery(EntityManager em, Order order) {
// use the identity of the related instance
return em.find(Delivery.class, order.getId());
}
</pre></div></div><br class="example-break"><p>
When your entity has multiple identity fields, at least one of which is a
relation to another entity, you can use an identity class (see
<a href="jpa_overview_pc_identity.html#jpa_overview_pc_identitycls" title="2.1.&nbsp; Identity Class">Section&nbsp;2.1, &#8220;
Identity Class
&#8221;</a> in the JPA Overview), or
an embedded identity object. Identity class fields corresponding to
entity identity fields should be of the same type as the related entity's
identity. If an embedded identity object is used, you must annotate the
relation field with both the <code class="literal">@ManyToOne</code> or
<code class="literal">@OneToOne</code> relation annotation and the
<code class="literal">@MappedById</code> annotation.
</p><div class="example"><a name="ref_guide_pc_oid_entitypk_idcls"></a><p class="title"><b>Example&nbsp;5.6.&nbsp;
Id Class for Entity Identity Fields
</b></p><div class="example-contents"><pre class="programlisting">
@Entity
public class Order {
@Id
private long id;
...
}
/**
* LineItem uses a compound primary key. Part of the compound key
* LineItemId is relation or reference to Order instance.
**/
@Entity
@IdClass(LineItemId.class)
public class LineItem {
@Id
private int index;
@Id
@ManyToOne
private Order order;
...
}
public class LineItemId {
public int index;
public long order; // same type as identity of Order i.e Order.id
// also the variable name must match the name of the
// variable in LineItem that refers to Order.
}
</pre></div></div><br class="example-break"><p>
In the example above, if <code class="classname">Order</code> had used an identity
class <code class="classname">OrderId</code> in place of a simple <code class="classname">long
</code> value, then the <code class="literal">LineItemId.order</code> field would
have been of type <code class="classname">OrderId</code>.
</p><div class="example"><a name="ref_guide_pc_oid_entitypk_embeded_id"></a><p class="title"><b>Example&nbsp;5.7.&nbsp;
Embedded Id for Entity Identity Fields
</b></p><div class="example-contents"><pre class="programlisting">
@Entity
public class Order {
@Id
private long id;
...
}
/**
* LineItem uses a compound primary key. Part of the compound key
* LineItemId is relation or reference to Order instance.
**/
@Entity
public class LineItem {
@EmbeddedId LineItemId id;
@ManyToOne
@MappedById("orderId") // The value element of the MappedById annotation
// must be used to specify the name of the primary
// key attribute to which the relationship
// corresponds. If the primary key referenced by
// the relationship attribute is of the same Java
// type as the dependent's primary key, then the
// value element is not specified.
private Order order;
...
}
@Embeddable
public class LineItemId {
public int index;
public long orderId;
}
</pre></div></div><br class="example-break"><p>
In the example above, the <code class="classname">LineItem</code> uses an embedded id to
represent its primary key. The primary key attribute corresponding to the
relationship in the <code class="classname">LineItemId</code> must be of the same
type as the primary key of the <code class="classname">Order</code>. The
<code class="literal">MappedById</code> annotation must be applied to the relationship
field <code class="literal">LineItem.order</code>.
</p></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="ref_guide_pc_oid_application"></a>4.3.&nbsp;
Application Identity Tool
</h3></div></div></div><a class="indexterm" name="d0e25784"></a><a class="indexterm" name="d0e25791"></a><p>
If you choose to use application identity, you may want to take advantage of
OpenJPA's application identity tool. The application
identity tool generates Java code implementing the identity class for any
persistent type using application identity. The code satisfies all the
requirements the specification places on identity classes. You can use it as-is,
or simply use it as a starting point, editing it to meet your needs.
</p><p>
Before you can run the application identity tool on a persistent class, the
class must be compiled and must have complete metadata. All primary key fields
must be marked as such in the metadata.
</p><p>
In JPA metadata, do not attempt to specify the <code class="literal">@IdClass</code>
annotation unless you are using the application identity tool to overwrite an
existing identity class. Attempting to set the value of the <code class="literal">@IdClass
</code> to a non-existent class will prevent your persistent class from
compiling. Instead, use the <code class="literal">-name</code> or <code class="literal">-suffix
</code> options described below to tell OpenJPA what name to give your
generated identity class. Once the application identity tool has generated the
class code, you can set the <code class="literal">@IdClass</code> annotation.
</p><p>
The application identity tool can be invoked via its Java class,
<a xmlns:xlink="http://www.w3.org/1999/xlink" href="../javadoc/org/apache/openjpa/enhance/ApplicationIdTool" target="_top">
<code class="classname">org.apache.openjpa.enhance.ApplicationIdTool</code></a>.
</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>
<a href="ref_guide_integration.html#ref_guide_integration_appidtool" title="1.3.&nbsp; Application Identity Tool Ant Task">Section&nbsp;1.3, &#8220;
Application Identity Tool Ant Task
&#8221;</a> describes the
application identity tool's Ant task.
</p></div><div class="example"><a name="ref_guide_pc_appid_appidtool"></a><p class="title"><b>Example&nbsp;5.8.&nbsp;
Using the Application Identity Tool
</b></p><div class="example-contents"><pre class="programlisting">
java org.apache.openjpa.enhance.ApplicationIdTool -s Id Magazine.java
</pre></div></div><br class="example-break"><p>
The application identity tool accepts the standard set of command-line arguments
defined by the configuration framework (see
<a href="ref_guide_conf_devtools.html" title="3.&nbsp; Command Line Configuration">Section&nbsp;3, &#8220;
Command Line Configuration
&#8221;</a>), including code formatting
flags described in <a href="ref_guide_conf_devtools.html#ref_guide_conf_devtools_format" title="3.1.&nbsp; Code Formatting">Section&nbsp;3.1, &#8220;
Code Formatting
&#8221;</a>. It
also accepts the following arguments:
</p><div class="itemizedlist"><ul type="disc"><li><p>
<code class="literal">-directory/-d &lt;output directory&gt;</code>: Path to the output
directory. If the directory does not match the generated oid class' package, the
package structure will be created beneath the directory. If not specified, the
tool will first try to find the directory of the <code class="filename">.java</code> file
for the persistence-capable class, and failing that will use the current
directory.
</p></li><li><p>
<code class="literal">-ignoreErrors/-i &lt;true/t | false/f&gt;</code>: If <code class="literal">false
</code>, an exception will be thrown if the tool is run on any class that
does not use application identity, or is not the base class in the inheritance
hierarchy (recall that subclasses never define the application identity class;
they inherit it from their persistent superclass).
</p></li><li><p>
<code class="literal">-token/-t &lt;token&gt;</code>: The token to use to separate
stringified primary key values in the string form of the object id. This option
is only used if you have multiple primary key fields. It defaults to "::".
</p></li><li><p>
<code class="literal">-name/-n &lt;id class name&gt;</code>: The name of the identity
class to generate. If this option is specified, you must run the tool on exactly
one class. If the class metadata already names an object id class, this option
is ignored. If the name is not fully qualified, the persistent class' package is
prepended to form the qualified name.
</p></li><li><p>
<code class="literal">-suffix/-s &lt;id class suffix&gt;</code>: A string to suffix each
persistent class name with to form the identity class name. This option is
overridden by <code class="literal">-name</code> or by any object id class specified in
metadata.
</p></li></ul></div><p>
Each additional argument to the tool must be one of the following:
</p><div class="itemizedlist"><ul type="disc"><li><p>
The full name of a persistent class.
</p></li><li><p>
The .java file for a persistent class.
</p></li><li><p>
The <code class="filename">.class</code> file of a persistent class.
</p></li></ul></div><p>
If you do not supply any arguments to the tool, it will act on the classes in
your persistent classes list (see <a href="ref_guide_pc.html#ref_guide_pc_pcclasses" title="1.&nbsp; Persistent Class List">Section&nbsp;1, &#8220;
Persistent Class List
&#8221;</a>).
</p></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="ref_guide_pc_oid_pkgen_autoinc"></a>4.4.&nbsp;
Autoassign / Identity Strategy Caveats
</h3></div></div></div><a class="indexterm" name="d0e25900"></a><a class="indexterm" name="d0e25905"></a><a class="indexterm" name="d0e25910"></a><p>
<a href="jpa_overview_meta_field.html#jpa_overview_meta_gen" title="2.4.&nbsp; Generated Value">Section&nbsp;2.4, &#8220;
Generated Value
&#8221;</a> explains how to use JPA's
<code class="literal">IDENTITY</code> generation type to automatically assign field
values. However, here are some additional caveats you should be aware of when
using <code class="literal">IDENTITY</code> generation:
</p><div class="orderedlist"><ol type="1"><li><p>
Your database must support auto-increment / identity columns, or some equivalent
(see <a href="ref_guide_dbsetup_dbsupport.html#ref_guide_dbsetup_dbsupport_oracle" title="4.4.&nbsp; OracleDictionary Properties">Section&nbsp;4.4, &#8220;
OracleDictionary Properties
&#8221;</a> for how to
configure a combination of triggers and sequences to fake auto-increment support
in Oracle).
</p></li><li><p>
Auto-increment / identity columns must be an integer or long integer type.
</p></li><li><p>
Databases support auto-increment / identity columns to varying degrees. Some do
not support them at all. Others only allow a single such column per table, and
require that it be the primary key column. More lenient databases may allow
non-primary key auto-increment columns, and may allow more than one per table.
See your database documentation for details.
</p></li></ol></div></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="ref_guide_pc_interfaces.html">Prev</a>&nbsp;</td><td width="20%" align="center"><a accesskey="u" href="ref_guide_pc.html">Up</a></td><td width="40%" align="right">&nbsp;<a accesskey="n" href="ref_guide_inverses.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">3.&nbsp;Managed Interfaces&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="manual.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;5.&nbsp;
Managed Inverses
</td></tr></table></div></body></html>