blob: c985246c157a84db73679416ca67174f0a7c7be0 [file] [log] [blame]
<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<chapter id="jpa_overview_mapping">
<title>
Mapping Metadata
</title>
<indexterm zone="jpa_overview_mapping">
<primary>
mapping metadata
</primary>
</indexterm>
<indexterm>
<primary>
entities
</primary>
<secondary>
mapping to database
</secondary>
<see>
mapping metadata
</see>
</indexterm>
<indexterm>
<primary>
metadata
</primary>
<secondary>
mapping metadata
</secondary>
<see>
mapping metadata
</see>
</indexterm>
<indexterm>
<primary>
ORM
</primary>
<seealso>
mapping metadata
</seealso>
</indexterm>
<indexterm zone="jpa_overview_mapping">
<primary>
JPA
</primary>
<secondary>
object-relational mapping
</secondary>
<seealso>
mapping metadata
</seealso>
</indexterm>
<para>
<emphasis>Object-relational mapping</emphasis> is the process of mapping
entities to relational database tables. In JPA, you perform
object/relational mapping through <emphasis>mapping metadata</emphasis>.
Mapping metadata uses annotations to describe how to link your object model to
your relational model.
</para>
<note>
<para>
OpenJPA offers tools to automate mapping and schema creation. See
<xref linkend="ref_guide_mapping"/> in the Reference Guide.
</para>
</note>
<para>
Throughout this chapter, we will draw on the object model introduced in
<xref linkend="jpa_overview_meta"/>. We present that model again below.
As we discuss various aspects of mapping metadata, we will zoom in on specific
areas of the model and show how we map the object layer to the relational layer.
</para>
<mediaobject>
<imageobject>
<!-- PNG image data, 553 x 580 (see README) -->
<imagedata fileref="img/jpa-meta-model.png" width="369px"/>
</imageobject>
</mediaobject>
<para>
All mapping metadata is optional. Where no explicit mapping metadata is given,
JPA uses the defaults defined by the specification. As we present
each mapping throughout this chapter, we also describe the defaults that apply
when the mapping is absent.
</para>
<note>
<para>
Mapping metadata is used primarily with schema generation. This metadata should not
be relied upon for validation prior to communicating with the database.
For example using the @Column(nullable=false) annotation does not do up front validation
that the value in the entity is correct.
</para>
</note>
<section id="jpa_overview_mapping_table">
<title>
Table
</title>
<indexterm zone="jpa_overview_mapping_table">
<primary>
mapping metadata
</primary>
<secondary>
class
</secondary>
<tertiary>
table attribute
</tertiary>
</indexterm>
<para>
The <classname>Table</classname> annotation specifies the table for an entity
class. If you omit the <classname>Table</classname> annotation, base entity
classes default to a table with their unqualified class name. The default table
of an entity subclass depends on the inheritance strategy, as you will see in
<xref linkend="jpa_overview_mapping_inher"/>.
</para>
<para>
<classname>Table</classname>s have the following properties:
</para>
<itemizedlist>
<listitem>
<para>
<literal>String name</literal>: The name of the table. Defaults to the
unqualified entity class name.
</para>
</listitem>
<listitem>
<para>
<literal>String schema</literal>: The table's schema. If you do not name a
schema, JPA uses the default schema for the database connection.
</para>
</listitem>
<listitem>
<para>
<literal>String catalog</literal>: The table's catalog. If you do not name a
catalog, JPA uses the default catalog for the database connection.
</para>
</listitem>
<listitem>
<para>
<literal>UniqueConstraint[] uniqueConstraints</literal>: An array of unique
constraints to place on the table. We cover unique constraints below. Defaults
to an empty array.
</para>
</listitem>
</itemizedlist>
<para>
The equivalent XML element is <literal>table</literal>. It has the following
attributes, which correspond to the annotation properties above:
</para>
<itemizedlist>
<listitem>
<para>
<literal>name</literal>
</para>
</listitem>
<listitem>
<para>
<literal>schema</literal>
</para>
</listitem>
<listitem>
<para>
<literal>catalog</literal>
</para>
</listitem>
</itemizedlist>
<para>
The <literal>table</literal> element also accepts nested <literal>
unique-constraint</literal> elements representing unique constraints. We will
detail unique constraints shortly.
</para>
<para>
Sometimes, some of the fields in a class are mapped to secondary tables. In that
case, use the class' <classname>Table</classname> annotation to name what you
consider the class' primary table. Later, we will see how to map certain fields
to other tables.
</para>
<para>
The example below maps classes to tables to separate schemas. The
<literal>CONTRACT</literal>, <literal>SUB</literal>, and <literal>LINE_ITEM
</literal> tables are in the <literal>CNTRCT</literal> schema; all other tables
are in the default schema.
</para>
<example id="jpa_overview_mapping_classex">
<title>
Mapping Classes
</title>
<programlisting>
package org.mag;
@Entity
@IdClass(Magazine.MagazineId.class)
@Table(name="MAG")
public class Magazine {
...
public static class MagazineId {
...
}
}
@Entity
@Table(name="ART")
public class Article {
...
}
package org.mag.pub;
@Entity
@Table(name="COMP")
public class Company {
...
}
@Entity
@Table(name="AUTH")
public class Author {
...
}
@Embeddable
public class Address {
...
}
package org.mag.subscribe;
@MappedSuperclass
public abstract class Document {
...
}
@Entity
@Table(schema="CNTRCT")
public class Contract
extends Document {
...
}
@Entity
@Table(name="SUB", schema="CNTRCT")
public class Subscription {
...
@Entity
@Table(name="LINE_ITEM", schema="CNTRCT")
public static class LineItem
extends Contract {
...
}
}
@Entity(name="Lifetime")
public class LifetimeSubscription
extends Subscription {
...
}
@Entity(name="Trial")
public class TrialSubscription
extends Subscription {
...
}
</programlisting>
<para>
The same mapping information expressed in XML:
</para>
<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;/mapped-superclass&gt;
&lt;entity class="org.mag.Magazine"&gt;
&lt;table name="MAG"/&gt;
&lt;id-class="org.mag.Magazine.MagazineId"/&gt;
...
&lt;/entity&gt;
&lt;entity class="org.mag.Article"&gt;
&lt;table name="ART"/&gt;
...
&lt;/entity&gt;
&lt;entity class="org.mag.pub.Company"&gt;
&lt;table name="COMP"/&gt;
...
&lt;/entity&gt;
&lt;entity class="org.mag.pub.Author"&gt;
&lt;table name="AUTH"/&gt;
...
&lt;/entity&gt;
&lt;entity class="org.mag.subcribe.Contract"&gt;
&lt;table schema="CNTRCT"/&gt;
...
&lt;/entity&gt;
&lt;entity class="org.mag.subcribe.Subscription"&gt;
&lt;table name="SUB" schema="CNTRCT"/&gt;
...
&lt;/entity&gt;
&lt;entity class="org.mag.subscribe.Subscription.LineItem"&gt;
&lt;table name="LINE_ITEM" schema="CNTRCT"/&gt;
...
&lt;/entity&gt;
&lt;entity class="org.mag.subscribe.LifetimeSubscription" name="Lifetime"&gt;
...
&lt;/entity&gt;
&lt;entity class="org.mag.subscribe.TrialSubscription" name="Trial"&gt;
...
&lt;/entity&gt;
&lt;embeddable class="org.mag.pub.Address"&gt;
...
&lt;/embeddable&gt;
&lt;/entity-mappings&gt;
</programlisting>
</example>
</section>
<section id="jpa_overview_mapping_unq">
<title>
Unique Constraints
</title>
<indexterm zone="jpa_overview_mapping_unq">
<primary>
mapping metadata
</primary>
<secondary>
unique constraints
</secondary>
<seealso>
unique constraints
</seealso>
</indexterm>
<indexterm zone="jpa_overview_mapping_unq">
<primary>
unique constraints
</primary>
</indexterm>
<para>
Unique constraints ensure that the data in a column or combination of columns is
unique for each row. A table's primary key, for example, functions as an
implicit unique constraint. In JPA, you represent other unique
constraints with an array of <classname> UniqueConstraint</classname>
annotations within the table annotation. The unique constraints you define are
used during table creation to generate the proper database constraints, and may
also be used at runtime to order <literal>INSERT</literal>, <literal>UPDATE
</literal>, and <literal>DELETE</literal> statements. For example, suppose there
is a unique constraint on the columns of field <literal>F</literal>. In the
same transaction, you remove an object <literal>A</literal> and persist a new
object <literal>B</literal>, both with the same <literal>F</literal> value. The
JPA runtime must ensure that the SQL deleting <literal>A</literal>
is sent to the database before the SQL inserting <literal>B</literal> to avoid a
unique constraint violation.
</para>
<para>
<classname>UniqueConstraint</classname> has these properties:
</para>
<itemizedlist>
<listitem>
<para>
<literal>String name</literal>: The name of the constraint. OpenJPA will choose
a name if you do not provide one, or will create an anonymous constraint.
</para>
</listitem>
<listitem>
<para>
<literal>String[] columnNames</literal>: The names of the columns the
constraint spans.
</para>
</listitem>
</itemizedlist>
<para>
In XML, unique constraints are represented by nesting <literal>
unique-constraint</literal> elements within the <literal> table</literal>
element. Each <literal>unique-constraint</literal> element in turn nests
<literal>column-name</literal> text elements to enumerate the constraint's
columns.
</para>
<example id="jpa_overview_mapping_unq_attrex">
<title>
Defining a Unique Constraint
</title>
<para>
The following defines a unique constraint on the <literal> TITLE</literal>
column of the <literal>ART</literal> table:
</para>
<programlisting>
@Entity
@Table(name="ART", uniqueConstraints=@UniqueConstraint(name="TITLE_CNSTR", columnNames="TITLE"))
public class Article {
...
}
</programlisting>
<para>
The same metadata expressed in XML form:
</para>
<programlisting>
&lt;entity class="org.mag.Article"&gt;
&lt;table name="ART"&gt;
&lt;unique-constraint&gt;
&lt;name&gt;TITLE_CNSTR&lt;/name&gt;
&lt;column-name&gt;TITLE&lt;/column-name&gt;
&lt;/unique-constraint&gt;
&lt;/table&gt;
...
&lt;/entity&gt;
</programlisting>
</example>
</section>
<section id="jpa_overview_mapping_column">
<title>
Column
</title>
<indexterm zone="jpa_overview_mapping_column">
<primary>
mapping metadata
</primary>
<secondary>
Column
</secondary>
</indexterm>
<indexterm zone="jpa_overview_mapping_column">
<primary>
Column
</primary>
<secondary>
in mapping metadata
</secondary>
<seealso>
mapping metadata
</seealso>
</indexterm>
<para>
In the previous section, we saw that a <classname>UniqueConstraint</classname>
uses an array of column names. Field mappings, however, use full-fledged
<classname>Column</classname> annotations. Column annotations have the following
properties:
</para>
<itemizedlist>
<listitem>
<para>
<indexterm>
<primary>
mapping metadata
</primary>
<secondary>
Column
</secondary>
<tertiary>
name property
</tertiary>
</indexterm>
<literal>String name</literal>: The column name. Defaults to the field name.
</para>
</listitem>
<listitem>
<para>
<indexterm>
<primary>
mapping metadata
</primary>
<secondary>
Column
</secondary>
<tertiary>
columnDefinition property
</tertiary>
</indexterm>
<literal>String columnDefinition</literal>: The database-specific column type
name. This property is only used by vendors that support creating tables from
your mapping metadata. During table creation, the vendor will use the value of
the <literal>columnDefinition</literal> as the declared column type. If no
<literal>columnDefinition</literal> is given, the vendor will choose an
appropriate default based on the field type combined with the column's length,
precision, and scale.
</para>
</listitem>
<listitem>
<para>
<indexterm>
<primary>
mapping metadata
</primary>
<secondary>
Column
</secondary>
<tertiary>
length property
</tertiary>
</indexterm>
<literal>int length</literal>: The column length. This property is typically
only used during table creation, though some vendors might use it to validate
data before flushing. <literal>CHAR</literal> and <literal>VARCHAR</literal>
columns typically default to a length of 255; other column types use the
database default.
</para>
</listitem>
<listitem>
<para>
<indexterm>
<primary>
mapping metadata
</primary>
<secondary>
Column
</secondary>
<tertiary>
precision property
</tertiary>
</indexterm>
<literal>int precision</literal>: The precision of a numeric column. This
property is often used in conjunction with <literal>scale</literal> to form the
proper column type name during table creation.
</para>
</listitem>
<listitem>
<para>
<indexterm>
<primary>
mapping metadata
</primary>
<secondary>
Column
</secondary>
<tertiary>
scale property
</tertiary>
</indexterm>
<literal>int scale</literal>: The number of decimal digits a numeric column can
hold. This property is often used in conjunction with <literal>precision
</literal> to form the proper column type name during table creation.
</para>
</listitem>
<listitem>
<para>
<indexterm>
<primary>
mapping metadata
</primary>
<secondary>
Column
</secondary>
<tertiary>
nullable property
</tertiary>
</indexterm>
<literal>boolean nullable</literal>: Whether the column can store null values.
Vendors may use this property both for table creation and at runtime; however,
it is never required. Defaults to <literal>true</literal>.
</para>
</listitem>
<listitem>
<para>
<indexterm>
<primary>
mapping metadata
</primary>
<secondary>
Column
</secondary>
<tertiary>
insertable property
</tertiary>
</indexterm>
<literal>boolean insertable</literal>: By setting this property to <literal>
false</literal>, you can omit the column from SQL <literal>INSERT</literal>
statements. Defaults to <literal>true</literal>.
</para>
</listitem>
<listitem>
<para>
<indexterm>
<primary>
mapping metadata
</primary>
<secondary>
Column
</secondary>
<tertiary>
updatable property
</tertiary>
</indexterm>
<literal>boolean updatable</literal>: By setting this property to <literal>
false</literal>, you can omit the column from SQL <literal>UPDATE</literal>
statements. Defaults to <literal>true</literal>.
</para>
</listitem>
<listitem>
<para>
<indexterm>
<primary>
mapping metadata
</primary>
<secondary>
Column
</secondary>
<tertiary>
table property
</tertiary>
</indexterm>
<literal>String table</literal>: Sometimes you will need to map fields to
tables other than the primary table. This property allows you specify that the
column resides in a secondary table. We will see how to map fields to secondary
tables later in the chapter.
</para>
</listitem>
</itemizedlist>
<para>
The equivalent XML element is <literal>column</literal>. This element has
attributes that are exactly equivalent to the <classname> Column</classname>
annotation's properties described above:
</para>
<itemizedlist>
<listitem>
<para>
<literal>name</literal>
</para>
</listitem>
<listitem>
<para>
<literal>column-definition</literal>
</para>
</listitem>
<listitem>
<para>
<literal>length</literal>
</para>
</listitem>
<listitem>
<para>
<literal>precision</literal>
</para>
</listitem>
<listitem>
<para>
<literal>scale</literal>
</para>
</listitem>
<listitem>
<para>
<literal>insertable</literal>
</para>
</listitem>
<listitem>
<para>
<literal>updatable</literal>
</para>
</listitem>
<listitem>
<para>
<literal>table</literal>
</para>
</listitem>
</itemizedlist>
</section>
<section id="jpa_overview_mapping_id">
<title>
Identity Mapping
</title>
<indexterm zone="jpa_overview_mapping_id">
<primary>
Id
</primary>
</indexterm>
<indexterm zone="jpa_overview_mapping_id">
<primary>
mapping metadata
</primary>
<secondary>
identity
</secondary>
</indexterm>
<indexterm zone="jpa_overview_mapping_id">
<primary>
identity
</primary>
<secondary>
mapping
</secondary>
</indexterm>
<para>
With our new knowledge of columns, we can map the identity fields of our
entities. The diagram below now includes primary key columns for our model's
tables. The primary key column for <classname>Author</classname> uses
nonstandard type <literal> INTEGER64</literal>, and the <literal>Magazine.isbn
</literal> field is mapped to a <literal>VARCHAR(9)</literal> column instead of
a <literal>VARCHAR(255)</literal> column, which is the default for string
fields. We do not need to point out either one of these oddities to the JPA
implementation for runtime use. If, however, we want to use the JPA
implementation to create our tables for us, it needs to know about
any desired non-default column types. Therefore, the example following the
diagram includes this data in its encoding of our mappings.
</para>
<mediaobject>
<imageobject>
<!-- PNG image data, 513 x 410 (see README) -->
<imagedata fileref="img/jpa-mapping-identity.png" width="341px"/>
</imageobject>
</mediaobject>
<para>
Note that many of our identity fields do not need to specify column information,
because they use the default column name and type.
</para>
<example id="jpa_overview_mapping_identityex">
<title>
Identity Mapping
</title>
<programlisting>
package org.mag;
@Entity
@IdClass(Magazine.MagazineId.class)
@Table(name="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"))
public class Article {
@Id 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 {
@Column(name="AID", columnDefinition="INTEGER64")
@Id 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")
public class Contract
extends Document {
...
}
@Entity
@Table(name="SUB", schema="CNTRCT")
public class Subscription {
@Id private long id;
...
@Entity
@Table(name="LINE_ITEM", schema="CNTRCT")
public static class LineItem
extends Contract {
...
}
}
@Entity(name="Lifetime")
public class LifetimeSubscription
extends Subscription {
...
}
@Entity(name="Trial")
public class TrialSubscription
extends Subscription {
...
}
</programlisting>
<para>
The same metadata for <literal>Magazine</literal> and <literal>Company</literal>
expressed in XML form:
</para>
<programlisting>
&lt;entity class="org.mag.Magazine"&gt;
&lt;id-class class="org.mag.Magazine.Magazine.MagazineId"/&gt;
&lt;table name="MAG"/&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.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;
</programlisting>
</example>
</section>
<section id="jpa_overview_mapping_sequence">
<title>
Generators
</title>
<indexterm zone="jpa_overview_mapping_sequence">
<primary>
generators
</primary>
<secondary>
mapping metadata
</secondary>
</indexterm>
<indexterm zone="jpa_overview_mapping_sequence">
<primary>
mapping metadata
</primary>
<secondary>
generators
</secondary>
<seealso>
TableGenerator
</seealso>
<seealso>
SequenceGenerator
</seealso>
</indexterm>
<para>
One aspect of identity mapping not covered in the previous section is JPA's
ability to automatically assign a value to your numeric identity fields using
<emphasis>generators</emphasis>. We discussed the available generator types in
<xref linkend="jpa_overview_meta_id"/>. Now we show you how to define
named generators.
</para>
<section id="jpa_overview_mapping_sequence_seqgen">
<title>
Sequence Generator
</title>
<indexterm zone="jpa_overview_mapping_sequence_seqgen">
<primary>
generators
</primary>
<secondary>
SequenceGenerator
</secondary>
</indexterm>
<indexterm zone="jpa_overview_mapping_sequence_seqgen">
<primary>
SequenceGenerator
</primary>
</indexterm>
<para>
Most databases allow you to create native sequences. These are database
structures that generate increasing numeric values. The <classname>
SequenceGenerator</classname> annotation represents a named database sequence.
You can place the annotation on any package, entity class, persistent field
declaration (if your entity uses field access), or getter method for a
persistent property (if your entity uses property access). <classname>
SequenceGenerator</classname> has the following properties:
</para>
<itemizedlist>
<listitem>
<para>
<indexterm>
<primary>
SequenceGenerator
</primary>
<secondary>
name property
</secondary>
</indexterm>
<literal>String name</literal>: The generator name. This property is required.
</para>
</listitem>
<listitem>
<para>
<indexterm>
<primary>
SequenceGenerator
</primary>
<secondary>
sequenceName property
</secondary>
</indexterm>
<literal>String sequenceName</literal>: The name of the database sequence. If
you do not specify the database sequence, your vendor will choose an appropriate
default.
</para>
</listitem>
<listitem>
<para>
<indexterm>
<primary>
SequenceGenerator
</primary>
<secondary>
initialValue property
</secondary>
</indexterm>
<literal>int initialValue</literal>: The initial sequence value.
</para>
</listitem>
<listitem>
<para>
<indexterm>
<primary>
SequenceGenerator
</primary>
<secondary>
allocationSize property
</secondary>
</indexterm>
<literal>int allocationSize</literal>: The number of values to allocate in
memory for each trip to the database. Allocating values in memory allows the JPA
runtime to avoid accessing the database for every sequence request.
This number also specifies the amount that the sequence value is incremented
each time the sequence is accessed. Defaults to 50.
</para>
</listitem>
<listitem>
<para>
<indexterm>
<primary>
SequenceGenerator
</primary>
<secondary>
schema property
</secondary>
</indexterm>
<literal>String schema</literal>: The sequence's schema. If you do not name a
schema, JPA uses the default schema for the database connection.
</para>
</listitem>
</itemizedlist>
<note>
<para>
OpenJPA allows you to use one of OpenJPA's built-in generator
implementations in the <literal>sequenceName</literal> property. You can also
set the <literal>sequenceName</literal> to <literal>system</literal> to use the
system sequence defined by the <link linkend="openjpa.Sequence"><literal>
openjpa.Sequence</literal></link> configuration property. See the Reference
Guide's <xref linkend="ref_guide_sequence"/> for details.
</para>
</note>
<para>
The XML element for a sequence generator is <literal>sequence-generator
</literal>. Its attributes mirror the above annotation's properties:
</para>
<itemizedlist>
<listitem>
<para>
<literal>name</literal>
</para>
</listitem>
<listitem>
<para>
<literal>sequence-name</literal>
</para>
</listitem>
<listitem>
<para>
<literal>initial-value</literal>
</para>
</listitem>
<listitem>
<para>
<literal>allocation-size</literal>
</para>
</listitem>
<listitem>
<para>
<literal>schema</literal>
</para>
</listitem>
</itemizedlist>
<para>
To use a sequence generator, set your <classname>GeneratedValue</classname>
annotation's <literal>strategy</literal> property to <literal>
GenerationType.SEQUENCE</literal>, and its <literal>generator</literal> property
to the sequence generator's declared name. Or equivalently, set your <literal>
generated-value</literal> XML element's <literal>strategy</literal> attribute to
<literal>SEQUENCE</literal> and its <literal>generator</literal> attribute to
the generator name.
</para>
</section>
<section id="jpa_overview_mapping_sequence_tablegen">
<title>
Table Generator
</title>
<indexterm zone="jpa_overview_mapping_sequence_tablegen">
<primary>
generators
</primary>
<secondary>
TableGenerator
</secondary>
</indexterm>
<indexterm zone="jpa_overview_mapping_sequence_tablegen">
<primary>
TableGenerator
</primary>
</indexterm>
<para>
A <classname>TableGenerator</classname> refers to a database table used to store
increasing sequence values for one or more entities. As with <classname>
SequenceGenerator</classname>, you can place the <classname>TableGenerator
</classname> annotation on any package, entity class, persistent field
declaration (if your entity uses field access), or getter method for a
persistent property (if your entity uses property access). <classname>
TableGenerator</classname> has the following properties:
</para>
<itemizedlist>
<listitem>
<para>
<indexterm>
<primary>
TableGenerator
</primary>
<secondary>
name property
</secondary>
</indexterm>
<literal>String name</literal>: The generator name. This property is required.
</para>
</listitem>
<listitem>
<para>
<indexterm>
<primary>
TableGenerator
</primary>
<secondary>
table property
</secondary>
</indexterm>
<literal>String table</literal>: The name of the generator table. If left
unspecified, your vendor will choose a default table.
</para>
</listitem>
<listitem>
<para>
<indexterm>
<primary>
TableGenerator
</primary>
<secondary>
schema property
</secondary>
</indexterm>
<literal>String schema</literal>: The named table's schema.
</para>
</listitem>
<listitem>
<para>
<indexterm>
<primary>
TableGenerator
</primary>
<secondary>
catalog property
</secondary>
</indexterm>
<literal>String catalog</literal>: The named table's catalog.
</para>
</listitem>
<listitem>
<para>
<indexterm>
<primary>
TableGenerator
</primary>
<secondary>
pkColumnName property
</secondary>
</indexterm>
<literal>String pkColumnName</literal>: The name of the primary key column in
the generator table. If unspecified, your implementation will choose a default.
</para>
</listitem>
<listitem>
<para>
<indexterm>
<primary>
TableGenerator
</primary>
<secondary>
valueColumnName property
</secondary>
</indexterm>
<literal>String valueColumnName</literal>: The name of the column that holds
the sequence value. If unspecified, your implementation will choose a default.
</para>
</listitem>
<listitem>
<para>
<indexterm>
<primary>
TableGenerator
</primary>
<secondary>
pkColumnValue property
</secondary>
</indexterm>
<literal>String pkColumnValue</literal>: The primary key column value of the
row in the generator table holding this sequence value. You can use the same
generator table for multiple logical sequences by supplying different <literal>
pkColumnValue</literal> s. If you do not specify a value, the implementation
will supply a default.
</para>
</listitem>
<listitem>
<para>
<indexterm>
<primary>
TableGenerator
</primary>
<secondary>
initialValue property
</secondary>
</indexterm>
<literal>int initialValue</literal>: The value of the generator's first issued
number.
</para>
</listitem>
<listitem>
<para>
<indexterm>
<primary>
TableGenerator
</primary>
<secondary>
allocationSize property
</secondary>
</indexterm>
<literal>int allocationSize</literal>: The number of values to allocate in
memory for each trip to the database. Allocating values in memory allows the JPA
runtime to avoid accessing the database for every sequence request.
This number also specifies the amount that the sequence value is incremented
each time the generator table is updated. Defaults to 50.
</para>
</listitem>
</itemizedlist>
<para>
The XML equivalent is the <literal>table-generator</literal> element. This
element's attributes correspond exactly to the above annotation's properties:
</para>
<itemizedlist>
<listitem>
<para>
<literal>name</literal>
</para>
</listitem>
<listitem>
<para>
<literal>table</literal>
</para>
</listitem>
<listitem>
<para>
<literal>schema</literal>
</para>
</listitem>
<listitem>
<para>
<literal>catalog</literal>
</para>
</listitem>
<listitem>
<para>
<literal>pk-column-name</literal>
</para>
</listitem>
<listitem>
<para>
<literal>value-column-name</literal>
</para>
</listitem>
<listitem>
<para>
<literal>pk-column-value</literal>
</para>
</listitem>
<listitem>
<para>
<literal>initial-value</literal>
</para>
</listitem>
<listitem>
<para>
<literal>allocation-size</literal>
</para>
</listitem>
</itemizedlist>
<para>
To use a table generator, set your <classname>GeneratedValue</classname>
annotation's <literal>strategy</literal> property to <literal>
GenerationType.TABLE</literal>, and its <literal>generator</literal> property to
the table generator's declared name. Or equivalently, set your <literal>
generated-value</literal> XML element's <literal>strategy</literal> attribute to
<literal>TABLE</literal> and its <literal>generator</literal> attribute to the
generator name.
</para>
</section>
<section id="jpa_overview_mapping_sequence_genex">
<title>
Example
</title>
<para>
Let's take advantage of generators in our entity model. Here are our updated
mappings.
</para>
<example id="jpa_overview_mapping_sequenceex">
<title>
Generator Mapping
</title>
<programlisting>
package org.mag;
@Entity
@IdClass(Magazine.MagazineId.class)
@Table(name="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(generate=GenerationType.IDENTITY)
private long id;
...
}
@Entity
@Table(schema="CNTRCT")
public class Contract
extends Document {
...
}
@Entity
@Table(name="SUB", schema="CNTRCT")
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")
public class LifetimeSubscription
extends Subscription {
...
}
@Entity(name="Trial")
public class TrialSubscription
extends Subscription {
...
}
</programlisting>
<para>
The same metadata for <literal>Article</literal> and <literal>Author</literal>
expressed in XML form:
</para>
<programlisting>
&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.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;
</programlisting>
</example>
</section>
</section>
<section id="jpa_overview_mapping_inher">
<title>
Inheritance
</title>
<indexterm zone="jpa_overview_mapping_inher">
<primary>
mapping metadata
</primary>
<secondary>
inheritance
</secondary>
<seealso>
inheritance
</seealso>
</indexterm>
<indexterm zone="jpa_overview_mapping_inher">
<primary>
inheritance
</primary>
<secondary>
mapping
</secondary>
</indexterm>
<indexterm zone="jpa_overview_mapping_inher">
<primary>
entities
</primary>
<secondary>
inheritance
</secondary>
<seealso>
inheritance
</seealso>
</indexterm>
<indexterm>
<primary>
impedance mismatch
</primary>
</indexterm>
<para>
In the 1990's programmers coined the term <emphasis>impedance mismatch
</emphasis> to describe the difficulties in bridging the object and relational
worlds. Perhaps no feature of object modeling highlights the impedance mismatch
better than inheritance. There is no natural, efficient way to represent an
inheritance relationship in a relational database.
</para>
<para>
<indexterm>
<primary>
mapping metadata
</primary>
<secondary>
inheritance
</secondary>
<tertiary>
strategy attribute
</tertiary>
</indexterm>
Luckily, JPA gives you a choice of inheritance strategies, making
the best of a bad situation. The base entity class defines the inheritance
strategy for the hierarchy with the <classname>Inheritance</classname>
annotation. <classname>Inheritance</classname> has the following properties:
</para>
<itemizedlist>
<listitem>
<para>
<literal>InheritanceType strategy</literal>: Enum value declaring the
inheritance strategy for the hierarchy. Defaults to <literal>
InheritanceType.SINGLE_TABLE</literal>. We detail each of the available
strategies below.
</para>
</listitem>
</itemizedlist>
<para>
The corresponding XML element is <literal>inheritance</literal>, which has a
single attribute:
</para>
<itemizedlist>
<listitem>
<para>
<literal>strategy</literal>: One of <literal>SINGLE_TABLE</literal>, <literal>
JOINED</literal>, or <literal>TABLE_PER_CLASS</literal>.
</para>
</listitem>
</itemizedlist>
<para>
The following sections describe JPA's standard inheritance strategies.
</para>
<note>
<para>
OpenJPA allows you to vary your inheritance strategy for each class, rather than
forcing a single strategy per inheritance hierarchy. See
<xref linkend="ref_guide_mapping_jpa"/> in the Reference Guide for
details.
</para>
</note>
<section id="jpa_overview_mapping_inher_single">
<title>
Single Table
</title>
<indexterm zone="jpa_overview_mapping_inher_single">
<primary>
mapping metadata
</primary>
<secondary>
inheritance
</secondary>
<tertiary>
SINGLE_TABLE strategy
</tertiary>
</indexterm>
<indexterm zone="jpa_overview_mapping_inher_single">
<primary>
inheritance
</primary>
<secondary>
SINGLE_TABLE strategy
</secondary>
</indexterm>
<para>
The <literal>InheritanceType.SINGLE_TABLE</literal> strategy maps all classes in
the hierarchy to the base class' table.
</para>
<mediaobject>
<imageobject>
<!-- PNG image data, 266 x 203 (see README) -->
<imagedata fileref="img/inher-superclass-table.png" width="177px"/>
</imageobject>
</mediaobject>
<para>
In our model, <classname>Subscription</classname> is mapped to the <literal>
CNTRCT.SUB</literal> table. <classname> LifetimeSubscription</classname>, which
extends <classname> Subscription</classname>, adds its field data to this table
as well.
</para>
<example id="jpa_overview_mapping_inher_singleex">
<title>
Single Table Mapping
</title>
<programlisting>
@Entity
@Table(name="SUB", schema="CNTRCT")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
public class Subscription {
...
}
@Entity(name="Lifetime")
public class LifetimeSubscription
extends Subscription {
...
}
</programlisting>
<para>
The same metadata expressed in XML form:
</para>
<programlisting>
&lt;entity class="org.mag.subcribe.Subscription"&gt;
&lt;table name="SUB" schema="CNTRCT"/&gt;
&lt;inheritance strategy="SINGLE_TABLE"/&gt;
...
&lt;/entity&gt;
&lt;entity class="org.mag.subscribe.LifetimeSubscription"&gt;
...
&lt;/entity&gt;
</programlisting>
</example>
<para>
Single table inheritance is the default strategy. Thus, we could omit the
<literal>@Inheritance</literal> annotation in the example above and get the same
result.
</para>
<note>
<para>
<indexterm>
<primary>
inheritance
</primary>
<secondary>
flat
</secondary>
</indexterm>
<indexterm>
<primary>
flat
</primary>
<seealso>
inheritance
</seealso>
</indexterm>
Mapping subclass state to the superclass table is often called <emphasis>flat
</emphasis> inheritance mapping.
</para>
</note>
<section id="jpa_overview_mapping_inher_single_adv">
<title>
Advantages
</title>
<indexterm zone="jpa_overview_mapping_inher_single_adv">
<primary>
inheritance
</primary>
<secondary>
SINGLE_TABLE strategy
</secondary>
<tertiary>
advantages
</tertiary>
</indexterm>
<para>
Single table inheritance mapping is the fastest of all inheritance models, since
it never requires a join to retrieve a persistent instance from the database.
Similarly, persisting or updating a persistent instance requires only a single
<literal>INSERT</literal> or <literal>UPDATE</literal> statement. Finally,
relations to any class within a single table inheritance hierarchy are just as
efficient as relations to a base class.
</para>
</section>
<section id="jpa_overview_mapping_inher_single_disadv">
<title>
Disadvantages
</title>
<indexterm zone="jpa_overview_mapping_inher_single_disadv">
<primary>
inheritance
</primary>
<secondary>
SINGLE_TABLE strategy
</secondary>
<tertiary>
disadvantages
</tertiary>
</indexterm>
<para>
The larger the inheritance model gets, the "wider" the mapped table gets, in
that for every field in the entire inheritance hierarchy, a column must exist in
the mapped table. This may have undesirable consequence on the database size,
since a wide or deep inheritance hierarchy will result in tables with many
mostly-empty columns.
</para>
</section>
</section>
<section id="jpa_overview_mapping_inher_joined">
<title>
Joined
</title>
<indexterm zone="jpa_overview_mapping_inher_joined">
<primary>
mapping metadata
</primary>
<secondary>
inheritance
</secondary>
<tertiary>
JOINED strategy
</tertiary>
</indexterm>
<indexterm zone="jpa_overview_mapping_inher_joined">
<primary>
inheritance
</primary>
<secondary>
JOINED strategy
</secondary>
</indexterm>
<para>
The <literal>InheritanceType.JOINED</literal> strategy uses a different table
for each class in the hierarchy. Each table only includes state declared in its
class. Thus to load a subclass instance, the JPA implementation must
read from the subclass table as well as the table of each ancestor class, up to
the base entity class.
</para>
<note>
<para>
<indexterm>
<primary>
inheritance
</primary>
<secondary>
vertical
</secondary>
</indexterm>
<indexterm>
<primary>
vertical
</primary>
<seealso>
inheritance
</seealso>
</indexterm>
Using joined subclass tables is also called <emphasis>vertical</emphasis>
inheritance mapping.
</para>
</note>
<mediaobject>
<imageobject>
<!-- PNG image data, 256 x 229 (see README) -->
<imagedata fileref="img/jpa-inher-joined.png" width="171px"/>
</imageobject>
</mediaobject>
<para>
<classname>PrimaryKeyJoinColumn</classname> annotations tell the JPA
implementation how to join each subclass table record to the corresponding
record in its direct superclass table. In our model, the <literal>LINE_ITEM.ID
</literal> column joins to the <literal>CONTRACT.ID</literal> column. The
<classname>PrimaryKeyJoinColumn</classname> annotation has the following
properties:
</para>
<itemizedlist>
<listitem>
<para>
<literal>String name</literal>: The name of the subclass table column. When
there is a single identity field, defaults to that field's column name.
</para>
</listitem>
<listitem>
<para>
<literal>String referencedColumnName</literal>: The name of the superclass
table column this subclass table column joins to. When there is a single
identity field, defaults to that field's column name.
</para>
</listitem>
<listitem>
<para>
<literal>String columnDefinition</literal>: This property has the same meaning
as the <literal>columnDefinition</literal> property on the <classname>Column
</classname> annotation, described in
<xref linkend="jpa_overview_mapping_column"/>.
</para>
</listitem>
</itemizedlist>
<para>
The XML equivalent is the <literal>primary-key-join-column</literal> element.
Its attributes mirror the annotation properties described above:
</para>
<itemizedlist>
<listitem>
<para>
<literal>name</literal>
</para>
</listitem>
<listitem>
<para>
<literal>referenced-column-name</literal>
</para>
</listitem>
<listitem>
<para>
<literal>column-definition</literal>
</para>
</listitem>
</itemizedlist>
<para>
The example below shows how we use <literal>InheritanceTable.JOINED</literal>
and a primary key join column to map our sample model according to the diagram
above. Note that a primary key join column is not strictly needed, because there
is only one identity column, and the subclass table column has the same name as
the superclass table column. In this situation, the defaults suffice. However,
we include the primary key join column for illustrative purposes.
</para>
<example id="jpa_overview_mapping_inher_joinedex">
<title>
Joined Subclass Tables
</title>
<programlisting>
@Entity
@Table(schema="CNTRCT")
@Inheritance(strategy=InheritanceType.JOINED)
public class Contract
extends Document {
...
}
public class Subscription {
...
@Entity
@Table(name="LINE_ITEM", schema="CNTRCT")
@PrimaryKeyJoinColumn(name="ID", referencedColumnName="ID")
public static class LineItem
extends Contract {
...
}
}
</programlisting>
<para>
The same metadata expressed in XML form:
</para>
<programlisting>
&lt;entity class="org.mag.subcribe.Contract"&gt;
&lt;table schema="CNTRCT"/&gt;
&lt;inheritance strategy="JOINED"/&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;
</programlisting>
</example>
<para>
When there are multiple identity columns, you must define multiple <classname>
PrimaryKeyJoinColumn</classname>s using the aptly-named <classname>
PrimaryKeyJoinColumns</classname> annotation. This annotation's value is an
array of <classname> PrimaryKeyJoinColumn</classname> s. We could rewrite
<classname>LineItem</classname>'s mapping as:
</para>
<programlisting>
@Entity
@Table(name="LINE_ITEM", schema="CNTRCT")
@PrimaryKeyJoinColumns({
@PrimaryKeyJoinColumn(name="ID", referencedColumnName="ID")
})
public static class LineItem
extends Contract {
...
}
</programlisting>
<para>
In XML, simply list as many <literal> primary-key-join-column</literal> elements
as necessary.
</para>
<section id="jpa_overview_mapping_inher_joined_adv">
<title>
Advantages
</title>
<indexterm zone="jpa_overview_mapping_inher_joined_adv">
<primary>
inheritance
</primary>
<secondary>
JOINED strategy
</secondary>
<tertiary>
advantages
</tertiary>
</indexterm>
<para>
The joined strategy has the following advantages:
</para>
<orderedlist>
<listitem>
<para>
<indexterm>
<primary>
normalized
</primary>
</indexterm>
Using joined subclass tables results in the most <emphasis>normalized</emphasis>
database schema, meaning the schema with the least spurious or redundant data.
</para>
</listitem>
<listitem>
<para>
As more subclasses are added to the data model over time, the only schema
modification that needs to be made is the addition of corresponding subclass
tables in the database (rather than having to change the structure of existing
tables).
</para>
</listitem>
<listitem>
<para>
Relations to a base class using this strategy can be loaded through standard
joins and can use standard foreign keys, as opposed to the machinations required
to load polymorphic relations to table-per-class base types, described below.
</para>
</listitem>
</orderedlist>
</section>
<section id="jpa_overview_mapping_inher_joined_disadv">
<title>
Disadvantages
</title>
<indexterm zone="jpa_overview_mapping_inher_joined_disadv">
<primary>
inheritance
</primary>
<secondary>
JOINED strategy
</secondary>
<tertiary>
disadvantages
</tertiary>
</indexterm>
<para>
Aside from certain uses of the table-per-class strategy described below, the
joined strategy is often the slowest of the inheritance models. Retrieving any
subclass requires one or more database joins, and storing subclasses requires
multiple <literal>INSERT</literal> or <literal>UPDATE</literal> statements. This
is only the case when persistence operations are performed on subclasses; if
most operations are performed on the least-derived persistent superclass, then
this mapping is very fast.
</para>
<note>
<para>
When executing a select against a hierarchy that uses joined subclass table
inheritance, you must consider how to load subclass state.
<xref linkend="ref_guide_perfpack_eager"/> in the Reference Guide
describes OpenJPA's options for efficient data loading.
</para>
</note>
</section>
</section>
<section id="jpa_overview_mapping_inher_tpc">
<title>
Table Per Class
</title>
<indexterm zone="jpa_overview_mapping_inher_tpc">
<primary>
mapping metadata
</primary>
<secondary>
inheritance
</secondary>
<tertiary>
TABLE_PER_CLASS strategy
</tertiary>
</indexterm>
<indexterm zone="jpa_overview_mapping_inher_tpc">
<primary>
inheritance
</primary>
<secondary>
TABLE_PER_CLASS strategy
</secondary>
</indexterm>
<para>
Like the <literal>JOINED</literal> strategy, the <literal>
InheritanceType.TABLE_PER_CLASS</literal> strategy uses a different table for
each class in the hierarchy. Unlike the <literal>JOINED</literal> strategy,
however, each table includes all state for an instance of the corresponding
class. Thus to load a subclass instance, the JPA implementation must
only read from the subclass table; it does not need to join to superclass
tables.
</para>
<mediaobject>
<imageobject>
<!-- PNG image data, 283 x 247 (see README) -->
<imagedata fileref="img/inher-tpc.png" width="189px"/>
</imageobject>
</mediaobject>
<para>
Suppose that our sample model's <classname>Magazine</classname> class has a
subclass <classname>Tabloid</classname>. The classes are mapped using the
table-per-class strategy, as in the diagram above. In a table-per-class mapping,
<classname> Magazine</classname>'s table <literal>MAG</literal> contains all
state declared in the base <classname>Magazine</classname> class. <classname>
Tabloid</classname> maps to a separate table, <literal> TABLOID</literal>. This
table contains not only the state declared in the <classname>Tabloid</classname>
subclass, but all the base class state from <classname>Magazine</classname> as
well. Thus the <literal>TABLOID</literal> table would contain columns for
<literal>isbn</literal>, <literal>title</literal>, and other <classname>
Magazine</classname> fields. These columns would default to the names used in
<classname>Magazine</classname>'s mapping metadata.
<xref linkend="jpa_overview_mapping_embed"/> will show you how to use
<literal>AttributeOverride</literal>s and <literal>AssociationOverride</literal>
s to override superclass field mappings.
</para>
<example id="jpa_overview_mapping_inher_tpcex">
<title>
Table Per Class Mapping
</title>
<programlisting>
@Entity
@Table(name="MAG")
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public class Magazine {
...
}
@Entity
@Table(name="TABLOID")
public class Tabloid
extends Magazine {
...
}
</programlisting>
<para>
And the same classes in XML:
</para>
<programlisting>
&lt;entity class="org.mag.Magazine"&gt;
&lt;table name="MAG"/&gt;
&lt;inheritance strategy="TABLE_PER_CLASS"/&gt;
...
&lt;/entity&gt;
&lt;entity class="org.mag.Tabloid"&gt;
&lt;table name="TABLOID"/&gt;
...
&lt;/entity&gt;
</programlisting>
</example>
<section id="jpa_overview_mapping_inher_tpc_adv">
<title>
Advantages
</title>
<indexterm zone="jpa_overview_mapping_inher_tpc_adv">
<primary>
inheritance
</primary>
<secondary>
TABLE_PER_CLASS strategy
</secondary>
<tertiary>
advantages
</tertiary>
</indexterm>
<para>
The table-per-class strategy is very efficient when operating on instances of a
known class. Under these conditions, the strategy never requires joining to
superclass or subclass tables. Reads, joins, inserts, updates, and deletes are
all efficient in the absence of polymorphic behavior. Also, as in the joined
strategy, adding additional classes to the hierarchy does not require modifying
existing class tables.
</para>
</section>
<section id="jpa_overview_mapping_inher_tpc_disadv">
<title>
Disadvantages
</title>
<indexterm zone="jpa_overview_mapping_inher_tpc_disadv">
<primary>
inheritance
</primary>
<secondary>
TABLE_PER_CLASS strategy
</secondary>
<tertiary>
disadvantages
</tertiary>
</indexterm>
<para>
Polymorphic relations to non-leaf classes in a table-per-class hierarchy have
many limitations. When the concrete subclass is not known, the related object
could be in any of the subclass tables, making joins through the relation
impossible. This ambiguity also affects identity lookups and queries; these
operations require multiple SQL <literal>SELECT</literal>s (one for each
possible subclass), or a complex <literal>UNION</literal>.
</para>
<note>
<para>
<xref linkend="ref_guide_mapping_limits_tpc"/> in the Reference Guide
describes the limitations OpenJPA places on table-per-class mapping.
</para>
</note>
</section>
</section>
<section id="jpa_overview_mapping_inher_together">
<title>
Putting it All Together
</title>
<para>
Now that we have covered JPA's inheritance strategies, we can update our mapping
document with inheritance information. Here is the complete model:
</para>
<mediaobject>
<imageobject>
<!-- PNG image data, 513 x 410 (see README) -->
<imagedata fileref="img/jpa-inher-all.png" width="341px"/>
</imageobject>
</mediaobject>
<para>
And here is the corresponding mapping metadata:
</para>
<example id="jpa_overview_mapping_inher_togetherex">
<title>
Inheritance Mapping
</title>
<programlisting>
package org.mag;
@Entity
@IdClass(Magazine.MagazineId.class)
@Table(name="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)
public class Contract
extends Document {
...
}
@Entity
@Table(name="SUB", schema="CNTRCT")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
public class Subscription {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private long id;
...
@Entity
@Table(name="LINE_ITEM", schema="CNTRCT")
@PrimaryKeyJoinColumn(name="ID", referencedColumnName="ID")
public static class LineItem
extends Contract {
...
}
}
@Entity(name="Lifetime")
public class LifetimeSubscription
extends Subscription {
...
}
@Entity(name="Trial")
public class TrialSubscription
extends Subscription {
...
}
</programlisting>
<para>
The same metadata expressed in XML form:
</para>
<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;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;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;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;/entity&gt;
&lt;entity class="org.mag.subscribe.TrialSubscription" name="Trial"&gt;
...
&lt;/entity&gt;
&lt;/entity-mappings&gt;
</programlisting>
</example>
</section>
</section>
<section id="jpa_overview_mapping_discrim">
<title>
Discriminator
</title>
<indexterm zone="jpa_overview_mapping_discrim">
<primary>
discriminator
</primary>
</indexterm>
<indexterm zone="jpa_overview_mapping_discrim">
<primary>
mapping metadata
</primary>
<secondary>
discriminator
</secondary>
<seealso>
discriminator
</seealso>
</indexterm>
<indexterm zone="jpa_overview_mapping_discrim">
<primary>
inheritance
</primary>
<secondary>
discriminator
</secondary>
<seealso>
discriminator
</seealso>
</indexterm>
<para>
The <link linkend="jpa_overview_mapping_inher_single">single table</link>
inheritance strategy results in a single table containing records for two or
more different classes in an inheritance hierarchy. Similarly, using the
<link linkend="jpa_overview_mapping_inher_joined"> joined</link> 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 <emphasis>
discriminator</emphasis> column.
</para>
<para>
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.
</para>
<para>
The <classname>DiscriminatorColumn</classname> annotation represents a
discriminator column. It has these properties:
</para>
<itemizedlist>
<listitem>
<para>
<literal>String name</literal>: The column name. Defaults to <literal>DTYPE
</literal>.
</para>
</listitem>
<listitem>
<para>
<literal>length</literal>: For string discriminator values, the length of the
column. Defaults to 31.
</para>
</listitem>
<listitem>
<para>
<literal>String columnDefinition</literal>: This property has the same meaning
as the <literal>columnDefinition</literal> property on the <classname>Column
</classname> annotation, described in
<xref linkend="jpa_overview_mapping_column"/>.
</para>
</listitem>
<listitem>
<para>
<literal>DiscriminatorType discriminatorType</literal>: Enum value declaring
the discriminator strategy of the hierarchy.
</para>
</listitem>
</itemizedlist>
<para>
The corresponding XML element is <literal> discriminator-column</literal>. Its
attributes mirror the annotation properties above:
</para>
<itemizedlist>
<listitem>
<para>
<literal>name</literal>
</para>
</listitem>
<listitem>
<para>
<literal>length</literal>
</para>
</listitem>
<listitem>
<para>
<literal>column-definition</literal>
</para>
</listitem>
<listitem>
<para>
<literal>discriminator-type</literal>: One of <literal>STRING</literal>,
<literal>CHAR</literal>, or <literal>INTEGER</literal>.
</para>
</listitem>
</itemizedlist>
<para>
The <classname>DiscriminatorValue</classname> 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 <classname>
DiscriminatorColumn</classname>'s <literal>discriminatorType</literal> property
above. The type defaults to <literal>DiscriminatorType.STRING</literal>, but
may be <literal> DiscriminatorType.CHAR</literal> or <literal>
DiscriminatorType.INTEGER</literal>. If you do not specify a <classname>
DiscriminatorValue</classname>, the provider will choose an appropriate
default.
</para>
<para>
The corresponding XML element is <literal>discriminator-value</literal>. The
text within this element is parsed as the discriminator value.
</para>
<note>
<para>
OpenJPA assumes your model employs a discriminator column if any of the
following are true:
</para>
<orderedlist>
<listitem>
<para>
The base entity explicitly declares an inheritance type of <literal>
SINGLE_TABLE</literal>.
</para>
</listitem>
<listitem>
<para>
The base entity sets a discriminator value.
</para>
</listitem>
<listitem>
<para>
The base entity declares a discriminator column.
</para>
</listitem>
</orderedlist>
<para>
Only <literal>SINGLE_TABLE</literal> inheritance hierarchies require a
discriminator column and values. <literal> JOINED</literal> hierarchies can use
a discriminator to make some operations more efficient, but do not require one.
<literal>TABLE_PER_CLASS</literal> hierarchies have no use for a discriminator.
</para>
<para>
OpenJPA defines additional discriminator strategies; see
<xref linkend="ref_guide_mapping_jpa"/> in the Reference Guide for
details. OpenJPA also supports final entity classes. OpenJPA does not use a
discriminator on final classes.
</para>
</note>
<para>
We can now translate our newfound knowledge of JPA discriminators into concrete
JPA mappings. We first extend our diagram with discriminator columns:
</para>
<mediaobject>
<imageobject>
<!-- PNG image data, 513 x 410 (see README) -->
<imagedata fileref="img/jpa-discrim-all.png" width="341px"/>
</imageobject>
</mediaobject>
<para>
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 <literal>DTYPE</literal> discriminator
column mapping do not need an explicit <classname>DiscriminatorColumn
</classname> annotation.
</para>
<example id="jpa_overview_mapping_discrimex">
<title>
Discriminator Mapping
</title>
<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 {
...
}
</programlisting>
<para>
The same metadata expressed in XML:
</para>
<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;
</programlisting>
</example>
</section>
<section id="jpa_overview_mapping_field">
<title>
Field Mapping
</title>
<indexterm zone="jpa_overview_mapping_field">
<primary>
mapping metadata
</primary>
<secondary>
field mapping
</secondary>
<seealso>
persistent fields
</seealso>
</indexterm>
<indexterm zone="jpa_overview_mapping_field">
<primary>
persistent fields
</primary>
<secondary>
mapping metadata
</secondary>
</indexterm>
<para>
The following sections enumerate the myriad of field mappings JPA
supports. JPA augments the persistence metadata covered in
<xref linkend="jpa_overview_meta"/> with many new object-relational
annotations. As we explore the library of standard mappings, we introduce each
of these enhancements in context.
</para>
<note>
<para>
OpenJPA supports many additional field types, and allows you to create custom
mappings for unsupported field types or database schemas. See the Reference
Guide's <xref linkend="ref_guide_mapping"/> for complete coverage of
OpenJPA's mapping capabilities.
</para>
</note>
<section id="jpa_overview_mapping_basic">
<title>
Basic Mapping
</title>
<indexterm zone="jpa_overview_mapping_basic">
<primary>
mapping metadata
</primary>
<secondary>
basic fields
</secondary>
<seealso>
persistent fields
</seealso>
</indexterm>
<indexterm zone="jpa_overview_mapping_basic">
<primary>
persistent fields
</primary>
<secondary>
basic
</secondary>
</indexterm>
<para>
A <emphasis>basic</emphasis> field mapping stores the field value directly into
a database column. The following field metadata types use basic mapping. These
types were defined in <xref linkend="jpa_overview_meta_field"/>.
</para>
<itemizedlist>
<listitem>
<para>
<link linkend="jpa_overview_meta_id"><classname>Id</classname></link> fields.
</para>
</listitem>
<listitem>
<para>
<link linkend="jpa_overview_meta_version"><classname> Version</classname></link>
fields.
</para>
</listitem>
<listitem>
<para>
<link linkend="jpa_overview_meta_basic"><classname>Basic</classname></link>
fields.
</para>
</listitem>
</itemizedlist>
<para>
In fact, you have already seen examples of basic field mappings in this chapter
- the mapping of all identity fields in
<xref linkend="jpa_overview_mapping_identityex"/>. As you saw in that
section, to write a basic field mapping you use the <classname>Column
</classname> annotation to describe the column the field value is stored in. We
discussed the <classname>Column</classname> annotation in
<xref linkend="jpa_overview_mapping_column"/>. Recall that the name of
the column defaults to the field name, and the type of the column defaults to an
appropriate type for the field type. These defaults allow you to sometimes omit
the annotation altogether.
</para>
<section id="jpa_overview_mapping_lob">
<title>
LOBs
</title>
<indexterm zone="jpa_overview_mapping_lob">
<primary>
LOB
</primary>
</indexterm>
<indexterm zone="jpa_overview_mapping_lob">
<primary>
mapping metadata
</primary>
<secondary>
LOB types
</secondary>
</indexterm>
<indexterm zone="jpa_overview_mapping_lob">
<primary>
annotations
</primary>
<secondary>
Lob
</secondary>
</indexterm>
<para>
Adding the <classname>Lob</classname> marker annotation to a basic field signals
that the data is to be stored as a LOB (Large OBject). If the field holds string
or character data, it will map to a <literal>CLOB</literal> (Character Large
OBject) database column. If the field holds any other data type, it will be
stored as binary data in a <literal>BLOB</literal> (Binary Large OBject) column.
The implementation will serialize the Java value if needed.
</para>
<para>
The equivalent XML element is <literal>lob</literal>, which has no children or
attributes.
</para>
<note>
<para>
OpenJPA also supports LOB streaming. See <xref linkend="ref_guide_streamsupport"/> in
the Reference Guide for details.
</para>
</note>
</section>
<section id="jpa_overview_mapping_enum">
<title>
Enumerated
</title>
<indexterm zone="jpa_overview_mapping_enum">
<primary>
Enumerated
</primary>
</indexterm>
<indexterm zone="jpa_overview_mapping_enum">
<primary>
mapping metadata
</primary>
<secondary>
enums
</secondary>
</indexterm>
<indexterm zone="jpa_overview_mapping_enum">
<primary>
annotations
</primary>
<secondary>
Enumerated
</secondary>
</indexterm>
<para>
You can apply the <classname>Enumerated</classname> annotation to your
<classname>Enum</classname> fields to control how they map to the database. The
<classname>Enumerated</classname> annotation's value one of the following
constants from the <classname>EnumType</classname> enum:
</para>
<itemizedlist>
<listitem>
<para>
<literal>EnumType.ORDINAL</literal>: The default. The persistence
implementation places the ordinal value of the enum in a numeric column. This is
an efficient mapping, but may break if you rearrange the Java enum declaration.
</para>
</listitem>
<listitem>
<para>
<literal>EnumType.STRING</literal>: Store the name of the enum value rather
than the ordinal. This mapping uses a <literal>VARCHAR</literal> column rather
than a numeric one.
</para>
</listitem>
</itemizedlist>
<para>
The <classname>Enumerated</classname> annotation is optional. Any un-annotated
enumeration field defaults to <literal>ORDINAL</literal> mapping.
</para>
<para>
The corresponding XML element is <literal>enumerated</literal>. Its embedded
text must be one of <literal>STRING</literal> or <literal>ORIDINAL</literal>.
</para>
</section>
<section id="jpa_overview_mapping_temporal">
<title>
Temporal Types
</title>
<indexterm zone="jpa_overview_mapping_temporal">
<primary>
mapping metadata
</primary>
<secondary>
temporal types
</secondary>
</indexterm>
<indexterm zone="jpa_overview_mapping_temporal">
<primary>
persistent fields
</primary>
<secondary>
temporal
</secondary>
</indexterm>
<para>
The <classname>Temporal</classname> annotation determines how the implementation
handles your basic <classname> java.util.Date</classname> and <classname>
java.util.Calendar</classname> fields at the JDBC level. The <classname>
Temporal</classname> annotation's value is a constant from the <classname>
TemporalType</classname> enum. Available values are:
</para>
<itemizedlist>
<listitem>
<para>
<literal>TemporalType.TIMESTAMP</literal>: The default. Use JDBC's timestamp
APIs to manipulate the column data.
</para>
</listitem>
<listitem>
<para>
<literal>TemporalType.DATE</literal>: Use JDBC's SQL date APIs to manipulate
the column data.
</para>
</listitem>
<listitem>
<para>
<literal>TemporalType.TIME</literal>: Use JDBC's time APIs to manipulate the
column data.
</para>
</listitem>
</itemizedlist>
<para>
If the <classname>Temporal</classname> annotation is omitted, the implementation
will treat the data as a timestamp.
</para>
<para>
The corresponding XML element is <literal>temporal</literal>, whose text value
must be one of: <literal>TIME</literal>, <literal>DATE</literal>, or <literal>
TIMESTAMP</literal>.
</para>
</section>
<section id="jpa_overview_mapping_basic_example">
<title>
The Updated Mappings
</title>
<para>
Below we present an updated diagram of our model and its associated database
schema, followed by the corresponding mapping metadata. Note that the mapping
metadata relies on defaults where possible. Also note that as a mapped
superclass, <classname>Document</classname> can define mappings that will
automatically transfer to its subclass' tables. In
<xref linkend="jpa_overview_mapping_embed"/>, you will see how a subclass
can override its mapped superclass' mappings.
</para>
<mediaobject>
<imageobject>
<!-- PNG image data, 580 x 553 (see README) -->
<imagedata fileref="img/jpa-basic-field.png" width="387px"/>
</imageobject>
</mediaobject>
<example id="jpa_overview_mapping_basicex">
<title>
Basic Field Mapping
</title>
<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;
@Column(name="VERS")
@Version private int version;
private String name;
private double price;
@Column(name="COPIES")
private int copiesSold;
...
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;
@Column(name="VERS")
@Version private int version;
private String title;
private byte[] content;
...
}
package org.mag.pub;
@Entity
@Table(name="COMP")
public class Company {
@Column(name="CID")
@Id private long id;
@Column(name="VERS")
@Version private int version;
private String name;
@Column(name="REV")
private double revenue;
...
}
@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;
@Column(name="VERS")
@Version private int version;
@Column(name="FNAME")
private String firstName;
@Column(name="LNAME")
private String lastName;
...
}
@Embeddable
public class Address {
...
}
package org.mag.subscribe;
@MappedSuperclass
public abstract class Document {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private long id;
@Column(name="VERS")
@Version private int version;
...
}
@Entity
@Table(schema="CNTRCT")
@Inheritance(strategy=InheritanceType.JOINED)
@DiscriminatorColumn(name="CTYPE")
public class Contract
extends Document {
@Lob
private String terms;
...
}
@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;
@Column(name="VERS")
@Version private int version;
@Column(name="START")
private Date startDate;
@Column(name="PAY")
private double payment;
...
@Entity
@Table(name="LINE_ITEM", schema="CNTRCT")
public static class LineItem
extends Contract {
@Column(name="COMM")
private String comments;
private double price;
private long num;
...
}
}
@Entity(name="Lifetime")
@DiscriminatorValue("2")
public class LifetimeSubscription
extends Subscription {
@Basic(fetch=FetchType.LAZY)
@Column(name="ELITE")
private boolean getEliteClub() { ... }
public void setEliteClub(boolean elite) { ... }
...
}
@Entity(name="Trial")
@DiscriminatorValue("3")
public class TrialSubscription
extends Subscription {
@Column(name="END")
public Date getEndDate() { ... }
public void setEndDate(Date end) { ... }
...
}
</programlisting>
<para>
The same metadata expressed in XML:
</para>
<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;version name="version"&gt;
&lt;column name="VERS"/&gt;
&lt;/version&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;basic name="name"/&gt;
&lt;basic name="price"/&gt;
&lt;basic name="copiesSold"&gt;
&lt;column name="COPIES"/&gt;
&lt;/basic&gt;
&lt;version name="version"&gt;
&lt;column name="VERS"/&gt;
&lt;/version&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", sequenceName="ART_SEQ"/&gt;
&lt;attributes&gt;
&lt;id name="id"&gt;
&lt;generated-value strategy="SEQUENCE" generator="ArticleSeq"/&gt;
&lt;/id&gt;
&lt;basic name="title"/&gt;
&lt;basic name="content"/&gt;
&lt;version name="version"&gt;
&lt;column name="VERS"/&gt;
&lt;/version&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;basic name="name"/&gt;
&lt;basic name="revenue"&gt;
&lt;column name="REV"/&gt;
&lt;/basic&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;basic name="firstName"&gt;
&lt;column name="FNAME"/&gt;
&lt;/basic&gt;
&lt;basic name="lastName"&gt;
&lt;column name="LNAME"/&gt;
&lt;/basic&gt;
&lt;version name="version"&gt;
&lt;column name="VERS"/&gt;
&lt;/version&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;basic name="terms"&gt;
&lt;lob/&gt;
&lt;/basic&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;basic name="payment"&gt;
&lt;column name="PAY"/&gt;
&lt;/basic&gt;
&lt;basic name="startDate"&gt;
&lt;column name="START"/&gt;
&lt;/basic&gt;
&lt;version name="version"&gt;
&lt;column name="VERS"/&gt;
&lt;/version&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;attributes&gt;
&lt;basic name="comments"&gt;
&lt;column name="COMM"/&gt;
&lt;/basic&gt;
&lt;basic name="price"/&gt;
&lt;basic name="num"/&gt;
...
&lt;/attributes&gt;
&lt;/entity&gt;
&lt;entity class="org.mag.subscribe.LifetimeSubscription" name="Lifetime"&gt;
&lt;discriminator-value&gt;2&lt;/discriminator-value&gt;
&lt;attributes&gt;
&lt;basic name="eliteClub" fetch="LAZY"&gt;
&lt;column name="ELITE"/&gt;
&lt;/basic&gt;
...
&lt;/attributes&gt;
&lt;/entity&gt;
&lt;entity class="org.mag.subscribe.TrialSubscription" name="Trial"&gt;
&lt;discriminator-value&gt;3&lt;/discriminator-value&gt;
&lt;attributes&gt;
&lt;basic name="endDate"&gt;
&lt;column name="END"/&gt;
&lt;/basic&gt;
...
&lt;/attributes&gt;
&lt;/entity&gt;
&lt;/entity-mappings&gt;
</programlisting>
</example>
</section>
</section>
<section id="jpa_overview_mapping_secondary">
<title>
Secondary Tables
</title>
<indexterm zone="jpa_overview_mapping_secondary">
<primary>
mapping metadata
</primary>
<secondary>
secondary table fields
</secondary>
<seealso>
persistent fields
</seealso>
</indexterm>
<indexterm zone="jpa_overview_mapping_secondary">
<primary>
persistent fields
</primary>
<secondary>
in secondary tables
</secondary>
</indexterm>
<para>
Sometimes a logical record is spread over multiple database tables. JPA
calls a class' declared table the <emphasis>primary</emphasis>
table, and calls other tables that make up a logical record <emphasis>secondary
</emphasis> tables. You can map any persistent field to a secondary table. Just
write the standard field mapping, then perform these two additional steps:
</para>
<orderedlist>
<listitem>
<para>
Set the <literal>table</literal> attribute of each of the field's columns or
join columns to the name of the secondary table.
</para>
</listitem>
<listitem>
<para>
Define the secondary table on the entity class declaration.
</para>
</listitem>
</orderedlist>
<para>
You define secondary tables with the <classname>SecondaryTable</classname>
annotation. This annotation has all the properties of the <classname>Table
</classname> annotation covered in <xref linkend="jpa_overview_mapping_table"/>
, plus a <literal> pkJoinColumns</literal> property.
</para>
<