blob: a31c55432f70c18c22d5628f8618ab38fcda38e5 [file] [log] [blame]
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>7.&nbsp; Discriminator</title><link rel="stylesheet" href="css/docbook.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.72.0"><link rel="start" href="manual.html" title="Apache OpenJPA User's Guide"><link rel="up" href="jpa_overview_mapping.html" title="Chapter&nbsp;12.&nbsp; Mapping Metadata"><link rel="prev" href="jpa_overview_mapping_inher.html" title="6.&nbsp; Inheritance"><link rel="next" href="jpa_overview_mapping_field.html" title="8.&nbsp; Field Mapping"></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">7.&nbsp;
Discriminator
</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="jpa_overview_mapping_inher.html">Prev</a>&nbsp;</td><th width="60%" align="center">Chapter&nbsp;12.&nbsp;
Mapping Metadata
</th><td width="20%" align="right">&nbsp;<a accesskey="n" href="jpa_overview_mapping_field.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="jpa_overview_mapping_discrim"></a>7.&nbsp;
Discriminator
</h2></div></div></div><a class="indexterm" name="d0e10839"></a><a class="indexterm" name="d0e10842"></a><a class="indexterm" name="d0e10849"></a><p>
The <a href="jpa_overview_mapping_inher.html#jpa_overview_mapping_inher_single" title="6.1.&nbsp; Single Table">single table</a>
inheritance strategy results in a single table containing records for two or
more different classes in an inheritance hierarchy. Similarly, using the
<a href="jpa_overview_mapping_inher.html#jpa_overview_mapping_inher_joined" title="6.2.&nbsp; Joined"> joined</a> strategy
results in the superclass table holding records for superclass instances as well
as for the superclass state of subclass instances. When selecting data, JPA
needs a way to differentiate a row representing an object of one class from a
row representing an object of another. That is the job of the <span class="emphasis"><em>
discriminator</em></span> column.
</p><p>
The discriminator column is always in the table of the base entity. It holds a
different value for records of each class, allowing the JPA runtime
to determine what class of object each row represents.
</p><p>
The <code class="classname">DiscriminatorColumn</code> annotation represents a
discriminator column. It has these properties:
</p><div class="itemizedlist"><ul type="disc"><li><p>
<code class="literal">String name</code>: The column name. Defaults to <code class="literal">DTYPE
</code>.
</p></li><li><p>
<code class="literal">length</code>: For string discriminator values, the length of the
column. Defaults to 31.
</p></li><li><p>
<code class="literal">String columnDefinition</code>: This property has the same meaning
as the <code class="literal">columnDefinition</code> property on the <code class="classname">Column
</code> annotation, described in
<a href="jpa_overview_mapping_column.html" title="3.&nbsp; Column">Section&nbsp;3, &#8220;
Column
&#8221;</a>.
</p></li><li><p>
<code class="literal">DiscriminatorType discriminatorType</code>: Enum value declaring
the discriminator strategy of the hierarchy.
</p></li></ul></div><p>
The corresponding XML element is <code class="literal"> discriminator-column</code>. Its
attribues mirror the annotation properties above:
</p><div class="itemizedlist"><ul type="disc"><li><p>
<code class="literal">name</code>
</p></li><li><p>
<code class="literal">length</code>
</p></li><li><p>
<code class="literal">column-definition</code>
</p></li><li><p>
<code class="literal">discriminator-type</code>: One of <code class="literal">STRING</code>,
<code class="literal">CHAR</code>, or <code class="literal">INTEGER</code>.
</p></li></ul></div><p>
The <code class="classname">DiscriminatorValue</code> annotation specifies the
discriminator value for each class. Though this annotation's value is always a
string, the implementation will parse it according to the <code class="classname">
DiscriminatorColumn</code>'s <code class="literal">discriminatorType</code> property
above. The type defaults to <code class="literal">DiscriminatorType.STRING</code>, but
may be <code class="literal"> DiscriminatorType.CHAR</code> or <code class="literal">
DiscriminatorType.INTEGER</code>. If you do not specify a <code class="classname">
DiscriminatorValue</code>, the provider will choose an appropriate
default.
</p><p>
The corresponding XML element is <code class="literal">discriminator-value</code>. The
text within this element is parsed as the discriminator value.
</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>
OpenJPA assumes your model employs a discriminator column if any of the
following are true:
</p><div class="orderedlist"><ol type="1"><li><p>
The base entity explicitly declares an inheritance type of <code class="literal">
SINGLE_TABLE</code>.
</p></li><li><p>
The base entity sets a discriminator value.
</p></li><li><p>
The base entity declares a discriminator column.
</p></li></ol></div><p>
Only <code class="literal">SINGLE_TABLE</code> inheritance hierarchies require a
discriminator column and values. <code class="literal"> JOINED</code> hierarchies can use
a discriminator to make some operations more efficient, but do not require one.
<code class="literal">TABLE_PER_CLASS</code> hierarchies have no use for a discriminator.
</p><p>
OpenJPA defines additional discriminator strategies; see
<a href="ref_guide_mapping_jpa.html" title="7.&nbsp; Additional JPA Mappings">Section&nbsp;7, &#8220;
Additional JPA Mappings
&#8221;</a> in the Reference Guide for
details. OpenJPA also supports final entity classes. OpenJPA does not use a
discriminator on final classes.
</p></div><p>
We can now translate our newfound knowledge of JPA discriminators into concrete
JPA mappings. We first extend our diagram with discriminator columns:
</p><div class="mediaobject"><table border="0" summary="manufactured viewport for HTML img" cellspacing="0" cellpadding="0" width="341"><tr><td><img src="img/jpa-discrim-all.png"></td></tr></table></div><p>
Next, we present the updated mapping document. Notice that in this version, we
have removed explicit inheritance annotations when the defaults sufficed. Also,
notice that entities using the default <code class="literal">DTYPE</code> discriminator
column mapping do not need an explicit <code class="classname">DiscriminatorColumn
</code> annotation.
</p><div class="example"><a name="jpa_overview_mapping_discrimex"></a><p class="title"><b>Example&nbsp;12.9.&nbsp;
Discriminator Mapping
</b></p><div class="example-contents"><pre class="programlisting">
package org.mag;
@Entity
@IdClass(Magazine.MagazineId.class)
@Table(name="MAG")
@DiscriminatorValue("Mag")
public class Magazine {
@Column(length=9)
@Id private String isbn;
@Id private String title;
...
public static class MagazineId {
...
}
}
@Entity
@Table(name="ART", uniqueConstraints=@Unique(columnNames="TITLE"))
@SequenceGenerator(name="ArticleSeq", sequenceName="ART_SEQ")
public class Article {
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="ArticleSeq")
private long id;
...
}
package org.mag.pub;
@Entity
@Table(name="COMP")
public class Company {
@Column(name="CID")
@Id private long id;
...
}
@Entity
@Table(name="AUTH")
public class Author {
@Id
@GeneratedValue(strategy=GenerationType.TABLE, generator="AuthorGen")
@TableGenerator(name="AuthorGen", table="AUTH_GEN", pkColumnName="PK",
valueColumnName="AID")
@Column(name="AID", columnDefinition="INTEGER64")
private long id;
...
}
@Embeddable
public class Address {
...
}
package org.mag.subscribe;
@MappedSuperclass
public abstract class Document {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private long id;
...
}
@Entity
@Table(schema="CNTRCT")
@Inheritance(strategy=InheritanceType.JOINED)
@DiscriminatorColumn(name="CTYPE")
public class Contract
extends Document {
...
}
@Entity
@Table(name="SUB", schema="CNTRCT")
@DiscriminatorColumn(name="KIND", discriminatorType=DiscriminatorType.INTEGER)
@DiscriminatorValue("1")
public class Subscription {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private long id;
...
@Entity
@Table(name="LINE_ITEM", schema="CNTRCT")
public static class LineItem
extends Contract {
...
}
}
@Entity(name="Lifetime")
@DiscriminatorValue("2")
public class LifetimeSubscription
extends Subscription {
...
}
@Entity(name="Trial")
@DiscriminatorValue("3")
public class TrialSubscription
extends Subscription {
...
}
</pre><p>
The same metadata expressed in XML:
</p><pre class="programlisting">
&lt;entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm orm_1_0.xsd"
version="1.0"&gt;
&lt;mapped-superclass class="org.mag.subscribe.Document"&gt;
&lt;attributes&gt;
&lt;id name="id"&gt;
&lt;generated-value strategy="IDENTITY"/&gt;
&lt;/id&gt;
...
&lt;/attributes&gt;
&lt;/mapped-superclass&gt;
&lt;entity class="org.mag.Magazine"&gt;
&lt;table name="MAG"/&gt;
&lt;id-class="org.mag.Magazine.MagazineId"/&gt;
&lt;discriminator-value&gt;Mag&lt;/discriminator-value&gt;
&lt;attributes&gt;
&lt;id name="isbn"&gt;
&lt;column length="9"/&gt;
&lt;/id&gt;
&lt;id name="title"/&gt;
...
&lt;/attributes&gt;
&lt;/entity&gt;
&lt;entity class="org.mag.Article"&gt;
&lt;table name="ART"&gt;
&lt;unique-constraint&gt;
&lt;column-name&gt;TITLE&lt;/column-name&gt;
&lt;/unique-constraint&gt;
&lt;/table&gt;
&lt;sequence-generator name="ArticleSeq" sequence-name="ART_SEQ"/&gt;
&lt;attributes&gt;
&lt;id name="id"&gt;
&lt;generated-value strategy="SEQUENCE" generator="ArticleSeq"/&gt;
&lt;/id&gt;
...
&lt;/attributes&gt;
&lt;/entity&gt;
&lt;entity class="org.mag.pub.Company"&gt;
&lt;table name="COMP"/&gt;
&lt;attributes&gt;
&lt;id name="id"&gt;
&lt;column name="CID"/&gt;
&lt;/id&gt;
...
&lt;/attributes&gt;
&lt;/entity&gt;
&lt;entity class="org.mag.pub.Author"&gt;
&lt;table name="AUTH"/&gt;
&lt;attributes&gt;
&lt;id name="id"&gt;
&lt;column name="AID" column-definition="INTEGER64"/&gt;
&lt;generated-value strategy="TABLE" generator="AuthorGen"/&gt;
&lt;table-generator name="AuthorGen" table="AUTH_GEN"
pk-column-name="PK" value-column-name="AID"/&gt;
&lt;/id&gt;
...
&lt;/attributes&gt;
&lt;/entity&gt;
&lt;entity class="org.mag.subcribe.Contract"&gt;
&lt;table schema="CNTRCT"/&gt;
&lt;inheritance strategy="JOINED"/&gt;
&lt;discriminator-column name="CTYPE"/&gt;
&lt;attributes&gt;
...
&lt;/attributes&gt;
&lt;/entity&gt;
&lt;entity class="org.mag.subcribe.Subscription"&gt;
&lt;table name="SUB" schema="CNTRCT"/&gt;
&lt;inheritance strategy="SINGLE_TABLE"/&gt;
&lt;discriminator-value&gt;1&lt;/discriminator-value&gt;
&lt;discriminator-column name="KIND" discriminator-type="INTEGER"/&gt;
&lt;attributes&gt;
&lt;id name="id"&gt;
&lt;generated-value strategy="IDENTITY"/&gt;
&lt;/id&gt;
...
&lt;/attributes&gt;
&lt;/entity&gt;
&lt;entity class="org.mag.subscribe.Subscription.LineItem"&gt;
&lt;table name="LINE_ITEM" schema="CNTRCT"/&gt;
&lt;primary-key-join-column name="ID" referenced-column-name="PK"/&gt;
...
&lt;/entity&gt;
&lt;entity class="org.mag.subscribe.LifetimeSubscription" name="Lifetime"&gt;
&lt;discriminator-value&gt;2&lt;/discriminator-value&gt;
...
&lt;/entity&gt;
&lt;entity class="org.mag.subscribe.TrialSubscription" name="Trial"&gt;
&lt;discriminator-value&gt;3&lt;/discriminator-value&gt;
...
&lt;/entity&gt;
&lt;/entity-mappings&gt;
</pre></div></div><br class="example-break"></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="jpa_overview_mapping_inher.html">Prev</a>&nbsp;</td><td width="20%" align="center"><a accesskey="u" href="jpa_overview_mapping.html">Up</a></td><td width="40%" align="right">&nbsp;<a accesskey="n" href="jpa_overview_mapping_field.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">6.&nbsp;
Inheritance
&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="manual.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;8.&nbsp;
Field Mapping
</td></tr></table></div></body></html>