The following sections enumerate the myriad of field mappings JPA
supports. JPA augments the persistence metadata covered in
Chapter 5,
Metadata
with many new object-relational
annotations. As we explore the library of standard mappings, we introduce each
of these enhancements in context.

Note

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 Chapter 7,
Mapping
for complete coverage of
OpenJPA's mapping capabilities.

In fact, you have already seen examples of basic field mappings in this chapter
- the mapping of all identity fields in
Example 12.3, “
Identity Mapping
”. As you saw in that
section, to write a basic field mapping you use the Column
annotation to describe the column the field value is stored in. We
discussed the Column annotation in
Section 3, “
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.

8.1.1.
LOBs

Adding the Lob 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 CLOB (Character Large
OBject) database column. If the field holds any other data type, it will be
stored as binary data in a BLOB (Binary Large OBject) column.
The implementation will serialize the Java value if needed.

The equivalent XML element is lob, which has no children or
attributes.

8.1.2.
Enumerated

You can apply the Enumerated annotation to your
Enum fields to control how they map to the database. The
Enumerated annotation's value one of the following
constants from the EnumType enum:

EnumType.ORDINAL: 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.

EnumType.STRING: Store the name of the enum value rather
than the ordinal. This mapping uses a VARCHAR column rather
than a numeric one.

The Enumerated annotation is optional. Any un-annotated
enumeration field defaults to ORDINAL mapping.

The corresponding XML element is enumerated. Its embedded
text must be one of STRING or ORIDINAL.

8.1.3.
Temporal Types

The Temporal annotation determines how the implementation
handles your basic java.util.Date and
java.util.Calendar fields at the JDBC level. The
Temporal annotation's value is a constant from the
TemporalType enum. Available values are:

TemporalType.TIMESTAMP: The default. Use JDBC's timestamp
APIs to manipulate the column data.

TemporalType.TIME: Use JDBC's time APIs to manipulate the
column data.

If the Temporal annotation is omitted, the implementation
will treat the data as a timestamp.

The corresponding XML element is temporal, whose text value
must be one of: TIME, DATE, or
TIMESTAMP.

8.1.4.
The Updated Mappings

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, Document can define mappings that will
automatically transfer to its subclass' tables. In
Section 8.3, “
Embedded Mapping
”, you will see how a subclass
can override its mapped superclass' mappings.

8.2.
Secondary Tables

Sometimes a logical record is spread over multiple database tables. JPA
calls a class' declared table the primary
table, and calls other tables that make up a logical record secondary
tables. You can map any persistent field to a secondary table. Just
write the standard field mapping, then perform these two additional steps:

Set the table attribute of each of the field's columns or
join columns to the name of the secondary table.

Define the secondary table on the entity class declaration.

You define secondary tables with the SecondaryTable
annotation. This annotation has all the properties of the Table
annotation covered in Section 1, “
Table
”
, plus a pkJoinColumns property.

The pkJoinColumns property is an array of
PrimaryKeyJoinColumns dictating how to join secondary table records
to their owning primary table records. Each PrimaryKeyJoinColumn
joins a secondary table column to a primary key column in the
primary table. See Section 6.2, “
Joined
”
above for coverage of PrimaryKeyJoinColumn's properties.

The corresponding XML element is secondary-table. This
element has all the attributes of the table element, but also
accepts nested primary-key-join-column elements.

8.3.
Embedded Mapping

Chapter 5,
Metadata
describes JPA's concept of
embeddable objects. The field values of embedded objects are stored
as part of the owning record, rather than as a separate database record. Thus,
instead of mapping a relation to an embeddable object as a foreign key, you map
all the fields of the embeddable instance to columns in the owning field's
table.

JPA defaults the embedded column names and descriptions to those of
the embeddable class' field mappings. The AttributeOverride
annotation overrides a basic embedded mapping. This annotation has
the following properties:

String name: The name of the embedded class' field being
mapped to this class' table.

Column column: The column defining the mapping of the
embedded class' field to this class' table.

The corresponding XML element is attribute-override. It has
a single name attribute to name the field being overridden,
and a single column child element.

To declare multiple overrides, use the AttributeOverrides
annotation, whose value is an array of AttributeOverride
s. In XML, simply list multiple attribute-override elements
in succession.

To override a many to one or one to one relationship, use the
AssociationOverride annotation in place of
AttributeOverride. AssociationOverride has
the following properties:

String name: The name of the embedded class' field being
mapped to this class' table.

You can also use attribute overrides on an entity class to override mappings
defined by its mapped superclass or table-per-class superclass. The example
below re-maps the Document.version field to the
Contract table's CVERSION column.

8.4.
Direct Relations

A direct relation is a non-embedded persistent field that holds a reference to
another entity. many to one
and one to one metadata field
types are mapped as direct relations. Our model has three direct relations:
Magazine's publisher field is a direct
relation to a Company, Magazine's
coverArticle field is a direct relation to
Article, and the LineItem.magazine field is a
direct relation to a Magazine. Direct relations are
represented in the database by foreign key columns:

You typically map a direct relation with JoinColumn
annotations describing how the local foreign key columns join to the primary key
columns of the related record. The JoinColumn annotation
exposes the following properties:

String name: The name of the foreign key column. Defaults to
the relation field name, plus an underscore, plus the name of the referenced
primary key column.

String referencedColumnName: The name of the primary key
column being joined to. If there is only one identity field in the related
entity class, the join column name defaults to the name of the identity field's
column.

boolean unique: Whether this column is guaranteed to hold
unique values for all rows. Defaults to false.

JoinColumn also has the same nullable
, insertable, updatable,
columnDefinition, and table properties as the
Column annotation. See
Section 3, “
Column
” for details on these
properties.

The join-column element represents a join column in XML. Its
attributes mirror the above annotation's properties:

name

referenced-column-name

unique

nullable

insertable

updatable

column-definition

table

When there are multiple columns involved in the join, as when a
LineItem references a Magazine in our model,
the JoinColumns annotation allows you to specify an array
of JoinColumn values. In XML, simply list multiple
join-column elements.

When the entities in a one to one relation join on shared primary key values
rather than separate foreign key columns, use the
PrimaryKeyJoinColumn(s) annotation or
primary-key-join-column elements in place of JoinColumn(s)
/ join-column elements.

8.5.
Join Table

A join table consists of two foreign keys. Each row of a
join table associates two objects together. JPA uses join tables to
represent collections of entity objects: one foreign key refers back to the
collection's owner, and the other refers to a collection element.

one to many and
many to many metadata field
types can map to join tables. Several fields in our model use join table
mappings, including Magazine.articles and
Article.authors.

You define join tables with the JoinTable annotation.
This annotation has the following properties:

String name: Table name. If not given, the name of the table
defaults to the name of the owning entity's table, plus an underscore, plus the
name of the related entity's table.

String catalog: Table catalog.

String schema: Table schema.

JoinColumn[] joinColumns: Array of JoinColumn
showing how to associate join table records with the owning row in
the primary table. This property mirrors the pkJoinColumns
property of the SecondaryTable annotation in
functionality. See Section 8.2, “
Secondary Tables
” to
refresh your memory on secondary tables.

If this is a bidirectional relation (see
Section 2.9.1, “
Bidirectional Relations
” ), the name of a join column
defaults to the inverse field name, plus an underscore, plus the referenced
primary key column name. Otherwise, the join column name defaults to the field's
owning entity name, plus an underscore, plus the referenced primary key column
name.

JoinColumn[] inverseJoinColumns: Array of
JoinColumns showing how to associate join table records with the
records that form the elements of the collection. These join columns are used
just like the join columns for direct relations, and they have the same naming
defaults. Read Section 8.4, “
Direct Relations
” for a review of
direct relation mapping.

join-table is the corresponding XML element. It has the same
attributes as the table element, but includes the ability to
nest join-column and inverse-join-column
elements as children. We have seen join-column elements
already; inverse-join-column elements have the same
attributes.

8.6.
Bidirectional Mapping

Section 2.9.1, “
Bidirectional Relations
” introduced bidirectional
relations. To map a bidirectional relation, you map one field normally using the
annotations we have covered throughout this chapter. Then you use the
mappedBy property of the other field's metadata annotation or the
corresponding mapped-by XML attribute to refer to the mapped
field. Look for this pattern in these bidirectional relations as you peruse the
complete mappings below:

Magazine.publisher and Company.mags.

Article.authors and Author.articles.

8.7.
Map Mapping

All map fields in JPA are modeled on either one to many or many to
many associations. The map key is always derived from an associated entity's
field. Thus map fields use the same mappings as any one to many or many to many
fields, namely dedicated join
tables or bidirectional
relations. The only additions are the MapKey
annotation and map-key element to declare the key field. We
covered these additions in in Section 2.13, “
Map Key
”.

The example below maps Subscription's map of
LineItems to the SUB_ITEMS join table. The key
for each map entry is the LineItem's num
field value.