blob: d1795584183adfe261937031df19dede092b5c98 [file] [log] [blame]
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>2.&nbsp; Entity Identity</title><base href="display"><link rel="stylesheet" type="text/css" href="css/docbook.css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.76.1"><link rel="home" href="manual.html" title="Apache OpenJPA 2.2 User's Guide"><link rel="up" href="jpa_overview_pc.html" title="Chapter&nbsp;4.&nbsp; Entity"><link rel="prev" href="jpa_overview_pc.html" title="Chapter&nbsp;4.&nbsp; Entity"><link rel="next" href="jpa_overview_pc_callbacks.html" title="3.&nbsp; Lifecycle Callbacks"></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">2.&nbsp;
Entity Identity
</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="jpa_overview_pc.html">Prev</a>&nbsp;</td><th width="60%" align="center">Chapter&nbsp;4.&nbsp;
Entity
</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="jpa_overview_pc_callbacks.html">Next</a></td></tr></table><hr></div><div class="section" title="2.&nbsp; Entity Identity"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="jpa_overview_pc_identity">2.&nbsp;
Entity Identity
</h2></div></div></div><div class="toc"><dl><dt><span class="section"><a href="jpa_overview_pc_identity.html#jpa_overview_pc_identitycls">2.1.
Identity Class
</a></span></dt><dd><dl><dt><span class="section"><a href="jpa_overview_pc_identity.html#jpa_overview_pc_identity_hierarchy">2.1.1.
Identity Hierarchies
</a></span></dt></dl></dd></dl></div>
<a class="indexterm" name="d5e722"></a>
<a class="indexterm" name="d5e726"></a>
<a class="indexterm" name="d5e729"></a>
<p>
<a class="indexterm" name="d5e733"></a>
<a class="indexterm" name="d5e736"></a>
<a class="indexterm" name="d5e739"></a>
<a class="indexterm" name="d5e742"></a>
Java recognizes two forms of object identity: numeric identity and qualitative
identity. If two references are <span class="emphasis"><em>numerically</em></span> identical, then
they refer to the same JVM instance in memory. You can test for this using the
<code class="literal">==</code> operator. <span class="emphasis"><em>Qualitative</em></span> identity, on
the other hand, relies on some user-defined criteria to determine whether two
objects are "equal". You test for qualitative identity using the <code class="methodname">
equals</code> method. By default, this method simply relies on numeric
identity.
</p>
<p>
JPA introduces another form of object identity, called <span class="emphasis"><em>entity
identity</em></span> or <span class="emphasis"><em>persistent identity</em></span>. Entity
identity tests whether two persistent objects represent the same state in the
datastore.
</p>
<p>
<a class="indexterm" name="d5e753"></a>
<a class="indexterm" name="d5e756"></a>
The entity identity of each persistent instance is encapsulated in its
<span class="emphasis"><em>identity field(s)</em></span>. If two entities of the same type have
the same identity field values, then the two entities represent the same state
in the datastore. Each entity's identity field values must be unique among all
other entities of the same type.
</p>
<p>
Identity fields must be primitives, primitive wrappers, <code class="classname">
String</code>s, <code class="classname">Date</code>s, <code class="classname">
Timestamp</code>s, or embeddable types.
</p>
<div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3>
<p>
OpenJPA supports entities as identity fields, as the Reference Guide discusses
in <a class="xref" href="ref_guide_pc_oid.html#ref_guide_pc_oid_entitypk" title="4.2.&nbsp; Entities as Identity Fields">Section&nbsp;4.2, &#8220;
Entities as Identity Fields
&#8221;</a>. For legacy schemas with binary
primary key columns, OpenJPA also supports using identity fields of type
<code class="classname">byte[]</code>. When you use a <code class="classname">byte[]</code>
identity field, you must create an identity class. Identity classes are
covered below.
</p>
</div>
<div class="warning" title="Warning" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Warning</h3>
<p>
Changing the fields of an embeddable instance while it is assigned to an
identity field has undefined results. Always treat embeddable identity instances
as immutable objects in your applications.
</p>
</div>
<p>
<a class="indexterm" name="d5e773"></a>
<a class="indexterm" name="d5e776"></a>
If you are dealing with a single persistence context (see
<a class="xref" href="jpa_overview_emfactory_perscontext.html" title="3.&nbsp; Persistence Context">Section&nbsp;3, &#8220;
Persistence Context
&#8221;</a>), then you do not
have to compare identity fields to test whether two entity references represent
the same state in the datastore. There is a much easier way: the <code class="literal">==
</code> operator. JPA requires that each persistence context maintain only
one JVM object to represent each unique datastore record. Thus, entity identity
is equivalent to numeric identity within a persistence context. This is referred
to as the <span class="emphasis"><em>uniqueness requirement</em></span>.
</p>
<p>
The uniqueness requirement is extremely important - without it, it would be
impossible to maintain data integrity. Think of what could happen if two
different objects in the same transaction were allowed to represent the same
persistent data. If you made different modifications to each of these objects,
which set of changes should be written to the datastore? How would your
application logic handle seeing two different "versions" of the same data?
Thanks to the uniqueness requirement, these questions do not have to be
answered.
</p>
<div class="section" title="2.1.&nbsp; Identity Class"><div class="titlepage"><div><div><h3 class="title" id="jpa_overview_pc_identitycls">2.1.&nbsp;
Identity Class
</h3></div></div></div><div class="toc"><dl><dt><span class="section"><a href="jpa_overview_pc_identity.html#jpa_overview_pc_identity_hierarchy">2.1.1.
Identity Hierarchies
</a></span></dt></dl></div>
<p>
<a class="indexterm" name="d5e786"></a>
<a class="indexterm" name="d5e789"></a>
If your entity has only one identity field, you can use the value of that field
as the entity's identity object in all <a class="link" href="jpa_overview_em.html" title="Chapter&nbsp;8.&nbsp; EntityManager">
<code class="classname">EntityManager</code></a> APIs. Otherwise, you must supply an
identity class to use for identity objects. Your identity class must meet the
following criteria:
</p>
<div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem">
<p>
The class must be public.
</p>
</li><li class="listitem">
<p>
The class must be serializable.
</p>
</li><li class="listitem">
<p>
The class must have a public no-args constructor.
</p>
</li><li class="listitem">
<p>
The names of the non-static fields or properties of the class must be the same
as the names of the identity fields or properties of the corresponding entity
class, and the types must be identical.
</p>
</li><li class="listitem">
<p>
The <code class="methodname">equals</code> and <code class="methodname">hashCode</code>
methods of the class must use the values of all fields or properties
corresponding to identity fields or properties in the entity class.
</p>
</li><li class="listitem">
<p>
If the class is an inner class, it must be <code class="literal">static</code>.
</p>
</li><li class="listitem">
<p>
All entity classes related by inheritance must use the same identity class, or
else each entity class must have its own identity class whose inheritance
hierarchy mirrors the inheritance hierarchy of the owning entity classes (see
<a class="xref" href="jpa_overview_pc_identity.html#jpa_overview_pc_identity_hierarchy" title="2.1.1.&nbsp; Identity Hierarchies">Section&nbsp;2.1.1, &#8220;
Identity Hierarchies
&#8221;</a>).
</p>
</li></ul></div>
<div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3>
<p>
Though you may still create identity classes by hand, OpenJPA provides the
<code class="classname">appidtool</code> to automatically generate proper identity
classes based on your identity fields. See
<a class="xref" href="ref_guide_pc_oid.html#ref_guide_pc_oid_application" title="4.3.&nbsp; Application Identity Tool">Section&nbsp;4.3, &#8220;
Application Identity Tool
&#8221;</a> of the Reference Guide.
</p>
</div>
<div class="example"><a name="jpa_overview_pc_identity_appidcode"></a><p class="title"><b>Example&nbsp;4.2.&nbsp;
Identity Class
</b></p><div class="example-contents">
<p>
This example illustrates a proper identity class for an entity with multiple
identity fields.
</p>
<pre class="programlisting">
/**
* Persistent class using application identity.
*/
public class Magazine {
private String isbn; // identity field
private String title; // identity field
// rest of fields and methods omitted
/**
* Application identity class for Magazine.
*/
public static class MagazineId {
// each identity field in the Magazine class must have a
// corresponding field in the identity class
public String isbn;
public String title;
/**
* Equality must be implemented in terms of identity field
* equality, and must use instanceof rather than comparing
* classes directly (some JPA implementations may subclass the
* identity class).
*/
public boolean equals(Object other) {
if (other == this)
return true;
if (!(other instanceof MagazineId))
return false;
MagazineId mi = (MagazineId) other;
return (isbn == mi.isbn
|| (isbn != null &amp;&amp; isbn.equals(mi.isbn)))
&amp;&amp; (title == mi.title
|| (title != null &amp;&amp; title.equals(mi.title)));
}
/**
* Hashcode must also depend on identity values.
*/
public int hashCode() {
return ((isbn == null) ? 0 : isbn.hashCode())
^ ((title == null) ? 0 : title.hashCode());
}
public String toString() {
return isbn + ":" + title;
}
}
}
</pre>
</div></div><br class="example-break">
<div class="section" title="2.1.1.&nbsp; Identity Hierarchies"><div class="titlepage"><div><div><h4 class="title" id="jpa_overview_pc_identity_hierarchy">2.1.1.&nbsp;
Identity Hierarchies
</h4></div></div></div>
<a class="indexterm" name="d5e823"></a>
<div class="mediaobject"><table border="0" summary="manufactured viewport for HTML img" cellspacing="0" cellpadding="0" width="213"><tr><td><img src="img/appid-hierarchy.png"></td></tr></table></div>
<p>
An alternative to having a single identity class for an entire inheritance
hierarchy is to have one identity class per level in the inheritance hierarchy.
The requirements for using a hierarchy of identity classes are as follows:
</p>
<div class="itemizedlist"><ul class="itemizedlist" type="disc"><li class="listitem">
<p>
The inheritance hierarchy of identity classes must exactly mirror the hierarchy
of the persistent classes that they identify. In the example pictured above,
abstract class <code class="classname">Person</code> is extended by abstract class
<code class="classname">Employee</code>, which is extended by non-abstract class
<code class="classname"> FullTimeEmployee</code>, which is extended by non-abstract
class <code class="classname">Manager</code>. The corresponding identity classes, then,
are an abstract <code class="classname">PersonId</code> class, extended by an abstract
<code class="classname">EmployeeId</code> class, extended by a non-abstract <code class="classname">
FullTimeEmployeeId</code> class, extended by a non-abstract <code class="classname">
ManagerId</code> class.
</p>
</li><li class="listitem">
<p>
Subclasses in the identity hierarchy may define additional identity fields until
the hierarchy becomes non-abstract. In the aforementioned example, <code class="classname">
Person</code> defines an identity field <code class="literal">ssn</code>, <code class="classname">
Employee</code> defines additional identity field <code class="literal">userName
</code>, and <code class="classname">FullTimeEmployee</code> adds a final identity
field, <code class="literal">empId</code>. However, <code class="classname">Manager</code> may not
define any additional identity fields, since it is a subclass of a non-abstract
class. The hierarchy of identity classes, of course, must match the identity
field definitions of the persistent class hierarchy.
</p>
</li><li class="listitem">
<p>
It is not necessary for each abstract class to declare identity fields. In the
previous example, the abstract <code class="classname">Person</code> and <code class="classname">
Employee</code> classes could declare no identity fields, and the first
concrete subclass <code class="classname">FullTimeEmployee</code> could define one or
more identity fields.
</p>
</li><li class="listitem">
<p>
All subclasses of a concrete identity class must be <code class="methodname">equals
</code> and <code class="methodname">hashCode</code>-compatible with the
concrete superclass. This means that in our example, a <code class="classname">ManagerId
</code> instance and a <code class="classname">FullTimeEmployeeId</code> instance
with the same identity field values should have the same hash code, and should
compare equal to each other using the <code class="methodname">equals</code> method of
either one. In practice, this requirement reduces to the following coding
practices:
</p>
<div class="orderedlist"><ol class="orderedlist" type="1"><li class="listitem">
<p>
Use <code class="literal">instanceof</code> instead of comparing <code class="classname">Class
</code> objects in the <code class="methodname">equals</code> methods of your
identity classes.
</p>
</li><li class="listitem">
<p>
An identity class that extends another non-abstract identity class should not
override <code class="methodname">equals</code> or <code class="methodname">hashCode</code>.
</p>
</li></ol></div>
</li></ul></div>
</div>
</div>
</div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="jpa_overview_pc.html">Prev</a>&nbsp;</td><td width="20%" align="center"><a accesskey="u" href="jpa_overview_pc.html">Up</a></td><td width="40%" align="right">&nbsp;<a accesskey="n" href="jpa_overview_pc_callbacks.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Chapter&nbsp;4.&nbsp;
Entity
&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="manual.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;3.&nbsp;
Lifecycle Callbacks
</td></tr></table></div></body></html>