| <html><head> |
| <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> |
| <title>8. Field Mapping</title><link rel="stylesheet" href="css/docbook.css" type="text/css"><base href="display"><meta name="generator" content="DocBook XSL Stylesheets V1.72.0"><link rel="start" href="manual.html" title="Apache OpenJPA 2.0 User's Guide"><link rel="up" href="jpa_overview_mapping.html" title="Chapter 13. Mapping Metadata"><link rel="prev" href="jpa_overview_mapping_discrim.html" title="7. Discriminator"><link rel="next" href="jpa_overview_mapping_full.html" title="9. The Complete Mappings"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">8. |
| Field Mapping |
| </th></tr><tr><td width="20%" align="left"><a accesskey="p" href="jpa_overview_mapping_discrim.html">Prev</a> </td><th width="60%" align="center">Chapter 13. |
| Mapping Metadata |
| </th><td width="20%" align="right"> <a accesskey="n" href="jpa_overview_mapping_full.html">Next</a></td></tr></table><hr></div><div class="section" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="jpa_overview_mapping_field"></a>8. |
| Field Mapping |
| </h2></div></div></div><div class="toc"><dl><dt><span class="section"><a href="jpa_overview_mapping_field.html#jpa_overview_mapping_basic">8.1. |
| Basic Mapping |
| </a></span></dt><dd><dl><dt><span class="section"><a href="jpa_overview_mapping_field.html#jpa_overview_mapping_lob">8.1.1. |
| LOBs |
| </a></span></dt><dt><span class="section"><a href="jpa_overview_mapping_field.html#jpa_overview_mapping_enum">8.1.2. |
| Enumerated |
| </a></span></dt><dt><span class="section"><a href="jpa_overview_mapping_field.html#jpa_overview_mapping_temporal">8.1.3. |
| Temporal Types |
| </a></span></dt><dt><span class="section"><a href="jpa_overview_mapping_field.html#jpa_overview_mapping_basic_example">8.1.4. |
| The Updated Mappings |
| </a></span></dt></dl></dd><dt><span class="section"><a href="jpa_overview_mapping_field.html#jpa_overview_mapping_secondary">8.2. |
| Secondary Tables |
| </a></span></dt><dt><span class="section"><a href="jpa_overview_mapping_field.html#jpa_overview_mapping_embed">8.3. |
| Embedded Mapping |
| </a></span></dt><dt><span class="section"><a href="jpa_overview_mapping_field.html#jpa_overview_mapping_rel">8.4. |
| Direct Relations |
| </a></span></dt><dt><span class="section"><a href="jpa_overview_mapping_field.html#jpa_overview_mapping_assoccoll">8.5. |
| Join Table |
| </a></span></dt><dt><span class="section"><a href="jpa_overview_mapping_field.html#jpa_overview_mapping_bidi">8.6. |
| Bidirectional Mapping |
| </a></span></dt><dt><span class="section"><a href="jpa_overview_mapping_field.html#jpa_overview_mapping_map">8.7. |
| Map Mapping |
| </a></span></dt></dl></div><a class="indexterm" name="d0e13029"></a><a class="indexterm" name="d0e13036"></a><p> |
| The following sections enumerate the myriad of field mappings JPA |
| supports. JPA augments the persistence metadata covered in |
| <a href="jpa_overview_meta.html" title="Chapter 5. Metadata">Chapter 5, <i xmlns:xlink="http://www.w3.org/1999/xlink"> |
| Metadata |
| </i></a> with many new object-relational |
| annotations. As we explore the library of standard mappings, we introduce each |
| of these enhancements in context. |
| </p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p> |
| 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 <a href="ref_guide_mapping.html" title="Chapter 7. Mapping">Chapter 7, <i xmlns:xlink="http://www.w3.org/1999/xlink"> |
| Mapping |
| </i></a> for complete coverage of |
| OpenJPA's mapping capabilities. |
| </p></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="jpa_overview_mapping_basic"></a>8.1. |
| Basic Mapping |
| </h3></div></div></div><div class="toc"><dl><dt><span class="section"><a href="jpa_overview_mapping_field.html#jpa_overview_mapping_lob">8.1.1. |
| LOBs |
| </a></span></dt><dt><span class="section"><a href="jpa_overview_mapping_field.html#jpa_overview_mapping_enum">8.1.2. |
| Enumerated |
| </a></span></dt><dt><span class="section"><a href="jpa_overview_mapping_field.html#jpa_overview_mapping_temporal">8.1.3. |
| Temporal Types |
| </a></span></dt><dt><span class="section"><a href="jpa_overview_mapping_field.html#jpa_overview_mapping_basic_example">8.1.4. |
| The Updated Mappings |
| </a></span></dt></dl></div><a class="indexterm" name="d0e13053"></a><a class="indexterm" name="d0e13060"></a><p> |
| A <span class="emphasis"><em>basic</em></span> field mapping stores the field value directly into |
| a database column. The following field metadata types use basic mapping. These |
| types were defined in <a href="jpa_overview_meta_field.html" title="2. Field and Property Metadata">Section 2, “ |
| Field and Property Metadata |
| ”</a>. |
| </p><div class="itemizedlist"><ul type="disc"><li><p> |
| <a href="jpa_overview_meta_field.html#jpa_overview_meta_id" title="2.3. Id"><code class="classname">Id</code></a> fields. |
| </p></li><li><p> |
| <a href="jpa_overview_meta_field.html#jpa_overview_meta_version" title="2.6. Version"><code class="classname"> Version</code></a> |
| fields. |
| </p></li><li><p> |
| <a href="jpa_overview_meta_field.html#jpa_overview_meta_basic" title="2.7. Basic"><code class="classname">Basic</code></a> |
| fields. |
| </p></li></ul></div><p> |
| In fact, you have already seen examples of basic field mappings in this chapter |
| - the mapping of all identity fields in |
| <a href="jpa_overview_mapping_id.html#jpa_overview_mapping_identityex" title="Example 13.3. Identity Mapping">Example 13.3, “ |
| Identity Mapping |
| ”</a>. As you saw in that |
| section, to write a basic field mapping you use the <code class="classname">Column |
| </code> annotation to describe the column the field value is stored in. We |
| discussed the <code class="classname">Column</code> annotation in |
| <a href="jpa_overview_mapping_column.html" title="3. Column">Section 3, “ |
| Column |
| ”</a>. 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. |
| </p><div class="section" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="jpa_overview_mapping_lob"></a>8.1.1. |
| LOBs |
| </h4></div></div></div><a class="indexterm" name="d0e13109"></a><a class="indexterm" name="d0e13112"></a><a class="indexterm" name="d0e13117"></a><p> |
| Adding the <code class="classname">Lob</code> 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 <code class="literal">CLOB</code> (Character Large |
| OBject) database column. If the field holds any other data type, it will be |
| stored as binary data in a <code class="literal">BLOB</code> (Binary Large OBject) column. |
| The implementation will serialize the Java value if needed. |
| </p><p> |
| The equivalent XML element is <code class="literal">lob</code>, which has no children or |
| attributes. |
| </p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p> |
| OpenJPA also supports LOB streaming. See <a href="ref_guide_mapping_jpa.html#ref_guide_streamsupport" title="7.11. LOB Streaming">Section 7.11, “ |
| LOB Streaming |
| ”</a> in |
| the Reference Guide for details. |
| </p></div></div><div class="section" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="jpa_overview_mapping_enum"></a>8.1.2. |
| Enumerated |
| </h4></div></div></div><a class="indexterm" name="d0e13146"></a><a class="indexterm" name="d0e13149"></a><a class="indexterm" name="d0e13154"></a><p> |
| You can apply the <code class="classname">Enumerated</code> annotation to your |
| <code class="classname">Enum</code> fields to control how they map to the database. The |
| <code class="classname">Enumerated</code> annotation's value one of the following |
| constants from the <code class="classname">EnumType</code> enum: |
| </p><div class="itemizedlist"><ul type="disc"><li><p> |
| <code class="literal">EnumType.ORDINAL</code>: 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. |
| </p></li><li><p> |
| <code class="literal">EnumType.STRING</code>: Store the name of the enum value rather |
| than the ordinal. This mapping uses a <code class="literal">VARCHAR</code> column rather |
| than a numeric one. |
| </p></li></ul></div><p> |
| The <code class="classname">Enumerated</code> annotation is optional. Any un-annotated |
| enumeration field defaults to <code class="literal">ORDINAL</code> mapping. |
| </p><p> |
| The corresponding XML element is <code class="literal">enumerated</code>. Its embedded |
| text must be one of <code class="literal">STRING</code> or <code class="literal">ORIDINAL</code>. |
| </p></div><div class="section" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="jpa_overview_mapping_temporal"></a>8.1.3. |
| Temporal Types |
| </h4></div></div></div><a class="indexterm" name="d0e13211"></a><a class="indexterm" name="d0e13216"></a><p> |
| The <code class="classname">Temporal</code> annotation determines how the implementation |
| handles your basic <code class="classname"> java.util.Date</code> and <code class="classname"> |
| java.util.Calendar</code> fields at the JDBC level. The <code class="classname"> |
| Temporal</code> annotation's value is a constant from the <code class="classname"> |
| TemporalType</code> enum. Available values are: |
| </p><div class="itemizedlist"><ul type="disc"><li><p> |
| <code class="literal">TemporalType.TIMESTAMP</code>: The default. Use JDBC's timestamp |
| APIs to manipulate the column data. |
| </p></li><li><p> |
| <code class="literal">TemporalType.DATE</code>: Use JDBC's SQL date APIs to manipulate |
| the column data. |
| </p></li><li><p> |
| <code class="literal">TemporalType.TIME</code>: Use JDBC's time APIs to manipulate the |
| column data. |
| </p></li></ul></div><p> |
| If the <code class="classname">Temporal</code> annotation is omitted, the implementation |
| will treat the data as a timestamp. |
| </p><p> |
| The corresponding XML element is <code class="literal">temporal</code>, whose text value |
| must be one of: <code class="literal">TIME</code>, <code class="literal">DATE</code>, or <code class="literal"> |
| TIMESTAMP</code>. |
| </p></div><div class="section" lang="en"><div class="titlepage"><div><div><h4 class="title"><a name="jpa_overview_mapping_basic_example"></a>8.1.4. |
| The Updated Mappings |
| </h4></div></div></div><p> |
| 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, <code class="classname">Document</code> can define mappings that will |
| automatically transfer to its subclass' tables. In |
| <a href="jpa_overview_mapping_field.html#jpa_overview_mapping_embed" title="8.3. Embedded Mapping">Section 8.3, “ |
| Embedded Mapping |
| ”</a>, you will see how a subclass |
| can override its mapped superclass' mappings. |
| </p><div class="mediaobject"><table border="0" summary="manufactured viewport for HTML img" cellspacing="0" cellpadding="0" width="387"><tr><td><img src="img/jpa-basic-field.png"></td></tr></table></div><div class="example"><a name="jpa_overview_mapping_basicex"></a><p class="title"><b>Example 13.10. |
| Basic Field Mapping |
| </b></p><div class="example-contents"><pre class="programlisting"> |
| package org.mag; |
| |
| @Entity |
| @IdClass(Magazine.MagazineId.class) |
| @Table(name="MAG") |
| @DiscriminatorValue("Mag") |
| public class Magazine { |
| |
| @Column(length=9) |
| @Id private String isbn; |
| @Id private String title; |
| |
| @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) { ... } |
| |
| ... |
| } |
| </pre><p> |
| The same metadata expressed in XML: |
| </p><pre class="programlisting"> |
| <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"> |
| <mapped-superclass class="org.mag.subscribe.Document"> |
| <attributes> |
| <id name="id"> |
| <generated-value strategy="IDENTITY"/> |
| </id> |
| <version name="version"> |
| <column name="VERS"/> |
| </version> |
| ... |
| </attributes> |
| </mapped-superclass> |
| <entity class="org.mag.Magazine"> |
| <table name="MAG"/> |
| <id-class="org.mag.Magazine.MagazineId"/> |
| <discriminator-value>Mag</discriminator-value> |
| <attributes> |
| <id name="isbn"> |
| <column length="9"/> |
| </id> |
| <id name="title"/> |
| <basic name="name"/> |
| <basic name="price"/> |
| <basic name="copiesSold"> |
| <column name="COPIES"/> |
| </basic> |
| <version name="version"> |
| <column name="VERS"/> |
| </version> |
| ... |
| </attributes> |
| </entity> |
| <entity class="org.mag.Article"> |
| <table name="ART"> |
| <unique-constraint> |
| <column-name>TITLE</column-name> |
| </unique-constraint> |
| </table> |
| <sequence-generator name="ArticleSeq", sequenceName="ART_SEQ"/> |
| <attributes> |
| <id name="id"> |
| <generated-value strategy="SEQUENCE" generator="ArticleSeq"/> |
| </id> |
| <basic name="title"/> |
| <basic name="content"/> |
| <version name="version"> |
| <column name="VERS"/> |
| </version> |
| ... |
| </attributes> |
| </entity> |
| <entity class="org.mag.pub.Company"> |
| <table name="COMP"/> |
| <attributes> |
| <id name="id"> |
| <column name="CID"/> |
| </id> |
| <basic name="name"/> |
| <basic name="revenue"> |
| <column name="REV"/> |
| </basic> |
| </attributes> |
| </entity> |
| <entity class="org.mag.pub.Author"> |
| <table name="AUTH"/> |
| <attributes> |
| <id name="id"> |
| <column name="AID" column-definition="INTEGER64"/> |
| <generated-value strategy="TABLE" generator="AuthorGen"/> |
| <table-generator name="AuthorGen" table="AUTH_GEN" |
| pk-column-name="PK" value-column-name="AID"/> |
| </id> |
| <basic name="firstName"> |
| <column name="FNAME"/> |
| </basic> |
| <basic name="lastName"> |
| <column name="LNAME"/> |
| </basic> |
| <version name="version"> |
| <column name="VERS"/> |
| </version> |
| ... |
| </attributes> |
| </entity> |
| <entity class="org.mag.subcribe.Contract"> |
| <table schema="CNTRCT"/> |
| <inheritance strategy="JOINED"/> |
| <discriminator-column name="CTYPE"/> |
| <attributes> |
| <basic name="terms"> |
| <lob/> |
| </basic> |
| ... |
| </attributes> |
| </entity> |
| <entity class="org.mag.subcribe.Subscription"> |
| <table name="SUB" schema="CNTRCT"/> |
| <inheritance strategy="SINGLE_TABLE"/> |
| <discriminator-value>1</discriminator-value> |
| <discriminator-column name="KIND" discriminator-type="INTEGER"/> |
| <attributes> |
| <id name="id"> |
| <generated-value strategy="IDENTITY"/> |
| </id> |
| <basic name="payment"> |
| <column name="PAY"/> |
| </basic> |
| <basic name="startDate"> |
| <column name="START"/> |
| </basic> |
| <version name="version"> |
| <column name="VERS"/> |
| </version> |
| ... |
| </attributes> |
| </entity> |
| <entity class="org.mag.subscribe.Subscription.LineItem"> |
| <table name="LINE_ITEM" schema="CNTRCT"/> |
| <primary-key-join-column name="ID" referenced-column-name="PK"/> |
| <attributes> |
| <basic name="comments"> |
| <column name="COMM"/> |
| </basic> |
| <basic name="price"/> |
| <basic name="num"/> |
| ... |
| </attributes> |
| </entity> |
| <entity class="org.mag.subscribe.LifetimeSubscription" name="Lifetime"> |
| <discriminator-value>2</discriminator-value> |
| <attributes> |
| <basic name="eliteClub" fetch="LAZY"> |
| <column name="ELITE"/> |
| </basic> |
| ... |
| </attributes> |
| </entity> |
| <entity class="org.mag.subscribe.TrialSubscription" name="Trial"> |
| <discriminator-value>3</discriminator-value> |
| <attributes> |
| <basic name="endDate"> |
| <column name="END"/> |
| </basic> |
| ... |
| </attributes> |
| </entity> |
| </entity-mappings> |
| </pre></div></div><br class="example-break"></div></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="jpa_overview_mapping_secondary"></a>8.2. |
| Secondary Tables |
| </h3></div></div></div><a class="indexterm" name="d0e13302"></a><a class="indexterm" name="d0e13309"></a><p> |
| Sometimes a logical record is spread over multiple database tables. JPA |
| calls a class' declared table the <span class="emphasis"><em>primary</em></span> |
| table, and calls other tables that make up a logical record <span class="emphasis"><em>secondary |
| </em></span> tables. You can map any persistent field to a secondary table. Just |
| write the standard field mapping, then perform these two additional steps: |
| </p><div class="orderedlist"><ol type="1"><li><p> |
| Set the <code class="literal">table</code> attribute of each of the field's columns or |
| join columns to the name of the secondary table. |
| </p></li><li><p> |
| Define the secondary table on the entity class declaration. |
| </p></li></ol></div><p> |
| You define secondary tables with the <code class="classname">SecondaryTable</code> |
| annotation. This annotation has all the properties of the <code class="classname">Table |
| </code> annotation covered in <a href="jpa_overview_mapping.html#jpa_overview_mapping_table" title="1. Table">Section 1, “ |
| Table |
| ”</a> |
| , plus a <code class="literal"> pkJoinColumns</code> property. |
| </p><p> |
| The <code class="literal">pkJoinColumns</code> property is an array of <code class="classname"> |
| PrimaryKeyJoinColumn</code>s dictating how to join secondary table records |
| to their owning primary table records. Each <code class="classname">PrimaryKeyJoinColumn |
| </code> joins a secondary table column to a primary key column in the |
| primary table. See <a href="jpa_overview_mapping_inher.html#jpa_overview_mapping_inher_joined" title="6.2. Joined">Section 6.2, “ |
| Joined |
| ”</a> |
| above for coverage of <code class="classname">PrimaryKeyJoinColumn</code>'s properties. |
| </p><p> |
| The corresponding XML element is <code class="literal">secondary-table</code>. This |
| element has all the attributes of the <code class="literal">table</code> element, but also |
| accepts nested <code class="literal">primary-key-join-column</code> elements. |
| </p><p> |
| In the following example, we move the <code class="literal">Article.content</code> field |
| we mapped in <a href="jpa_overview_mapping_field.html#jpa_overview_mapping_basic" title="8.1. Basic Mapping">Section 8.1, “ |
| Basic Mapping |
| ”</a> into a joined |
| secondary table, like so: |
| </p><div class="mediaobject"><table border="0" summary="manufactured viewport for HTML img" cellspacing="0" cellpadding="0" width="189"><tr><td><img src="img/secondary-table.png"></td></tr></table></div><div class="example"><a name="jpa_overview_mapping_secondaryex"></a><p class="title"><b>Example 13.11. |
| Secondary Table Field Mapping |
| </b></p><div class="example-contents"><pre class="programlisting"> |
| package org.mag; |
| |
| @Entity |
| @Table(name="ART") |
| @SecondaryTable(name="ART_DATA", |
| pkJoinColumns=@PrimaryKeyJoinColumn(name="ART_ID", referencedColumnName="ID")) |
| public class Article { |
| |
| @Id private long id; |
| |
| @Column(table="ART_DATA") |
| private byte[] content; |
| |
| ... |
| } |
| </pre><p> |
| And in XML: |
| </p><pre class="programlisting"> |
| <entity class="org.mag.Article"> |
| <table name="ART"/> |
| <secondary-table name="ART_DATA"> |
| <primary-key-join-column name="ART_ID" referenced-column-name="ID"/> |
| </secondary-table> |
| <attributes> |
| <id name="id"/> |
| <basic name="content"> |
| <column table="ART_DATA"/> |
| </basic> |
| ... |
| </attributes> |
| </entity> |
| </pre></div></div><br class="example-break"></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="jpa_overview_mapping_embed"></a>8.3. |
| Embedded Mapping |
| </h3></div></div></div><a class="indexterm" name="d0e13395"></a><a class="indexterm" name="d0e13402"></a><p> |
| <a href="jpa_overview_meta.html" title="Chapter 5. Metadata">Chapter 5, <i xmlns:xlink="http://www.w3.org/1999/xlink"> |
| Metadata |
| </i></a> describes JPA's concept of <span class="emphasis"><em> |
| embeddable</em></span> 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. |
| </p><div class="mediaobject"><table border="0" summary="manufactured viewport for HTML img" cellspacing="0" cellpadding="0" width="309"><tr><td><img src="img/jpa-embedded.png"></td></tr></table></div><p> |
| JPA defaults the embedded column names and descriptions to those of |
| the embeddable class' field mappings. The <code class="classname"> AttributeOverride |
| </code> annotation overrides a basic embedded mapping. This annotation has |
| the following properties: |
| </p><div class="itemizedlist"><ul type="disc"><li><p> |
| <code class="literal">String name</code>: The name of the embedded class' field being |
| mapped to this class' table. |
| </p></li><li><p> |
| <code class="literal">Column column</code>: The column defining the mapping of the |
| embedded class' field to this class' table. |
| </p></li></ul></div><p> |
| The corresponding XML element is <code class="literal"> attribute-override</code>. It has |
| a single <code class="literal">name</code> attribute to name the field being overridden, |
| and a single <code class="literal">column</code> child element. |
| </p><p> |
| To declare multiple overrides, use the <code class="classname">AttributeOverrides</code> |
| annotation, whose value is an array of <code class="classname">AttributeOverride</code> |
| s. In XML, simply list multiple <code class="literal">attribute-override</code> elements |
| in succession. |
| </p><p> |
| To override a many to one or one to one relationship, use the <code class="classname"> |
| AssociationOverride</code> annotation in place of <code class="classname"> |
| AttributeOverride</code>. <code class="classname"> AssociationOverride</code> has |
| the following properties: |
| </p><div class="itemizedlist"><ul type="disc"><li><p> |
| <code class="literal">String name</code>: The name of the embedded class' field being |
| mapped to this class' table. |
| </p></li><li><p> |
| <code class="literal">JoinColumn[] joinColumns</code>: The foreign key columns joining to |
| the related record. |
| </p></li></ul></div><p> |
| The corresponding XML element is <code class="literal"> association-override</code>. It |
| has a single <code class="literal">name</code> attribute to name the field being |
| overridden, and one or more <code class="literal">join-column</code> child elements. |
| </p><p> |
| To declare multiple relation overrides, use the <code class="classname"> AssociationOverrides |
| </code> annotation, whose value is an array of <code class="classname"> |
| AssociationOverride</code> s. In XML, simply list multiple <code class="literal"> |
| association-override</code> elements in succession. |
| </p><div class="example"><a name="jpa_overview_mapping_embedex"></a><p class="title"><b>Example 13.12. |
| Embedded Field Mapping |
| </b></p><div class="example-contents"><p> |
| In this example, <code class="classname">Company</code> overrides the default mapping of |
| <code class="literal">Address.street</code> and <code class="literal">Address.city</code>. All |
| other embedded mappings are taken from the <code class="classname">Address</code> |
| embeddable class. |
| </p><pre class="programlisting"> |
| package org.mag.pub; |
| |
| @Entity |
| @Table(name="COMP") |
| public class Company { |
| |
| @Embedded |
| @AttributeOverrides({ |
| @AttributeOverride(name="street", column=@Column(name="STRT")), |
| @AttributeOverride(name="city", column=@Column(name="ACITY")) |
| }) |
| private Address address; |
| |
| ... |
| } |
| |
| @Entity |
| @Table(name="AUTH") |
| public class Author { |
| |
| // use all defaults from Address class mappings |
| private Address address; |
| |
| ... |
| } |
| |
| @Embeddable |
| public class Address { |
| |
| private String street; |
| private String city; |
| @Column(columnDefinition="CHAR(2)") |
| private String state; |
| private String zip; |
| } |
| </pre><p> |
| The same metadata expressed in XML: |
| </p><pre class="programlisting"> |
| <entity class="org.mag.pub.Company"> |
| <table name="COMP"/> |
| <attributes> |
| ... |
| <embedded name="address"> |
| <attribute-override name="street"> |
| <column name="STRT"/> |
| </attribute-override> |
| <attribute-override name="city"> |
| <column name="ACITY"/> |
| </attribute-override> |
| </embedded> |
| </attributes> |
| </entity> |
| <entity class="org.mag.pub.Author"> |
| <table name="AUTH"/> |
| <attributes> |
| <embedded name="address"> |
| <!-- use all defaults from Address --> |
| </embedded> |
| </attributes> |
| </entity> |
| <embeddable class="org.mag.pub.Address"> |
| <attributes> |
| <basic name="street"/> |
| <basic name="city"/> |
| <basic name="state"> |
| <column column-definition="CHAR(2)"/> |
| </basic> |
| <basic name="zip"/> |
| </attributes> |
| </embeddable> |
| </pre></div></div><br class="example-break"><p> |
| 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 <code class="literal">Document.version</code> field to the <code class="classname"> |
| Contract</code> table's <code class="literal">CVERSION</code> column. |
| </p><div class="example"><a name="jpa_overview_mapping_joined_overex"></a><p class="title"><b>Example 13.13. |
| Mapping Mapped Superclass Field |
| </b></p><div class="example-contents"><pre class="programlisting"> |
| @MappedSuperclass |
| public abstract class Document { |
| |
| @Column(name="VERS") |
| @Version private int version; |
| |
| ... |
| } |
| |
| @Entity |
| @Table(schema="CNTRCT") |
| @Inheritance(strategy=InheritanceType.JOINED) |
| @DiscriminatorColumn(name="CTYPE") |
| @AttributeOverride(name="version", column=@Column(name="CVERSION")) |
| public class Contract |
| extends Document { |
| ... |
| } |
| </pre><p> |
| The same metadata expressed in XML form: |
| </p><pre class="programlisting"> |
| <mapped-superclass class="org.mag.subcribe.Document"> |
| <attributes> |
| <version name="version"> |
| <column name="VERS"> |
| </version> |
| ... |
| </attributes> |
| </mapped-superclass> |
| <entity class="org.mag.subcribe.Contract"> |
| <table schema="CNTRCT"/> |
| <inheritance strategy="JOINED"/> |
| <discriminator-column name="CTYPE"/> |
| <attribute-override name="version"> |
| <column name="CVERSION"/> |
| </attribute-override> |
| <attributes> |
| ... |
| </attributes> |
| </entity> |
| </pre></div></div><br class="example-break"></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="jpa_overview_mapping_rel"></a>8.4. |
| Direct Relations |
| </h3></div></div></div><a class="indexterm" name="d0e13550"></a><a class="indexterm" name="d0e13557"></a><a class="indexterm" name="d0e13562"></a><a class="indexterm" name="d0e13567"></a><p> |
| A direct relation is a non-embedded persistent field that holds a reference to |
| another entity. <a href="jpa_overview_meta_field.html#jpa_overview_meta_manytoone" title="2.9. Many To One">many to one</a> |
| and <a href="jpa_overview_meta_field.html#jpa_overview_meta_onetoone" title="2.11. One To One">one to one</a> metadata field |
| types are mapped as direct relations. Our model has three direct relations: |
| <code class="classname">Magazine</code>'s <code class="literal">publisher</code> field is a direct |
| relation to a <code class="classname">Company</code>, <code class="classname">Magazine</code>'s |
| <code class="literal">coverArticle</code> field is a direct relation to <code class="classname"> |
| Article</code>, and the <code class="literal">LineItem.magazine</code> field is a |
| direct relation to a <code class="classname">Magazine</code>. Direct relations are |
| represented in the database by foreign key columns: |
| </p><div class="mediaobject"><table border="0" summary="manufactured viewport for HTML img" cellspacing="0" cellpadding="0" width="249"><tr><td><img src="img/jpa-direct-relation.png"></td></tr></table></div><p> |
| You typically map a direct relation with <code class="classname">JoinColumn</code> |
| annotations describing how the local foreign key columns join to the primary key |
| columns of the related record. The <code class="classname">JoinColumn</code> annotation |
| exposes the following properties: |
| </p><div class="itemizedlist"><ul type="disc"><li><p> |
| <code class="literal">String name</code>: 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. |
| </p></li><li><p> |
| <code class="literal">String referencedColumnName</code>: 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. |
| </p></li><li><p> |
| <code class="literal">boolean unique</code>: Whether this column is guaranteed to hold |
| unique values for all rows. Defaults to false. |
| </p></li></ul></div><p> |
| <code class="classname">JoinColumn</code> also has the same <code class="literal"> nullable</code> |
| , <code class="literal">insertable</code>, <code class="literal"> updatable</code>, <code class="literal"> |
| columnDefinition</code>, and <code class="literal">table</code> properties as the |
| <code class="classname"> Column</code> annotation. See |
| <a href="jpa_overview_mapping_column.html" title="3. Column">Section 3, “ |
| Column |
| ”</a> for details on these |
| properties. |
| </p><p> |
| The <code class="literal">join-column</code> element represents a join column in XML. Its |
| attributes mirror the above annotation's properties: |
| </p><div class="itemizedlist"><ul type="disc"><li><p> |
| <code class="literal">name</code> |
| </p></li><li><p> |
| <code class="literal">referenced-column-name</code> |
| </p></li><li><p> |
| <code class="literal">unique</code> |
| </p></li><li><p> |
| <code class="literal">nullable</code> |
| </p></li><li><p> |
| <code class="literal">insertable</code> |
| </p></li><li><p> |
| <code class="literal">updatable</code> |
| </p></li><li><p> |
| <code class="literal">column-definition</code> |
| </p></li><li><p> |
| <code class="literal">table</code> |
| </p></li></ul></div><p> |
| When there are multiple columns involved in the join, as when a <code class="classname"> |
| LineItem</code> references a <code class="classname">Magazine</code> in our model, |
| the <code class="classname">JoinColumns</code> annotation allows you to specify an array |
| of <code class="classname">JoinColumn</code> values. In XML, simply list multiple |
| <code class="literal">join-column</code> elements. |
| </p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p> |
| OpenJPA supports many non-standard joins. See |
| <a href="ref_guide_mapping_notes_nonstdjoins.html" title="6. Non-Standard Joins">Section 6, “ |
| Non-Standard Joins |
| ”</a> in the Reference |
| Guide for details. |
| </p></div><div class="example"><a name="jpa_overview_mapping_relex"></a><p class="title"><b>Example 13.14. |
| Direct Relation Field Mapping |
| </b></p><div class="example-contents"><pre class="programlisting"> |
| package org.mag; |
| |
| @Table(name="AUTH") |
| public class Magazine { |
| |
| @Column(length=9) |
| @Id private String isbn; |
| @Id private String title; |
| |
| @OneToOne |
| @JoinColumn(name="COVER_ID" referencedColumnName="ID") |
| private Article coverArticle; |
| |
| @ManyToOne |
| @JoinColumn(name="PUB_ID" referencedColumnName="CID") |
| private Company publisher; |
| |
| ... |
| } |
| |
| @Table(name="ART") |
| public class Article { |
| |
| @Id private long id; |
| |
| ... |
| } |
| |
| |
| package org.mag.pub; |
| |
| @Table(name="COMP") |
| public class Company { |
| |
| @Column(name="CID") |
| @Id private long id; |
| |
| ... |
| } |
| |
| |
| package org.mag.subscribe; |
| |
| public class Subscription { |
| ... |
| |
| @Table(name="LINE_ITEM", schema="CNTRCT") |
| public static class LineItem |
| extends Contract { |
| |
| @ManyToOne |
| @JoinColumns({ |
| @JoinColumn(name="MAG_ISBN" referencedColumnName="ISBN"), |
| @JoinColumn(name="MAG_TITLE" referencedColumnName="TITLE") |
| }) |
| private Magazine magazine; |
| |
| ... |
| } |
| } |
| </pre><p> |
| The same metadata expressed in XML form: |
| </p><pre class="programlisting"> |
| <entity class="org.mag.Magazine"> |
| <table name="MAG"/> |
| <id-class="org.mag.Magazine.MagazineId"/> |
| <attributes> |
| <id name="isbn"> |
| <column length="9"/> |
| </id> |
| <id name="title"/> |
| <one-to-one name="coverArticle"> |
| <join-column name="COVER_ID" referenced-column-name="ID"/> |
| </one-to-one> |
| <many-to-one name="publisher"> |
| <join-column name="PUB_IC" referenced-column-name="CID"/> |
| </many-to-one> |
| ... |
| </attributes> |
| </entity> |
| <entity class="org.mag.Article"> |
| <table name="ART"/> |
| <attributes> |
| <id name="id"/> |
| ... |
| </attributes> |
| </entity> |
| <entity class="org.mag.pub.Company"> |
| <table name="COMP"/> |
| <attributes> |
| <id name="id"> |
| <column name="CID"/> |
| </id> |
| ... |
| </attributes> |
| </entity> |
| <entity class="org.mag.subscribe.Subscription.LineItem"> |
| <table name="LINE_ITEM" schema="CNTRCT"/> |
| <primary-key-join-column name="ID" referenced-column-name="PK"/> |
| <attributes> |
| <many-to-one name="magazine"> |
| <join-column name="MAG_ISBN" referenced-column-name="ISBN"/> |
| <join-column name="MAG_TITLE" referenced-column-name="TITLE"/> |
| </many-to-one> |
| ... |
| </attributes> |
| </entity> |
| </pre></div></div><br class="example-break"><p> |
| When the entities in a one to one relation join on shared primary key values |
| rather than separate foreign key columns, use the <code class="classname"> |
| PrimaryKeyJoinColumn(s)</code> annotation or <code class="literal"> |
| primary-key-join-column</code> elements in place of <code class="classname">JoinColumn(s) |
| </code> / <code class="literal"> join-column</code> elements. |
| </p></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="jpa_overview_mapping_assoccoll"></a>8.5. |
| Join Table |
| </h3></div></div></div><a class="indexterm" name="d0e13762"></a><a class="indexterm" name="d0e13769"></a><a class="indexterm" name="d0e13774"></a><a class="indexterm" name="d0e13777"></a><a class="indexterm" name="d0e13782"></a><p> |
| A <span class="emphasis"><em>join table</em></span> 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. |
| </p><p> |
| <a href="jpa_overview_meta_field.html#jpa_overview_meta_onetomany" title="2.10. One To Many">one to many</a> and |
| <a href="jpa_overview_meta_field.html#jpa_overview_meta_manytomany" title="2.12. Many To Many">many to many</a> metadata field |
| types can map to join tables. Several fields in our model use join table |
| mappings, including <code class="literal">Magazine.articles</code> and <code class="literal"> |
| Article.authors</code>. |
| </p><div class="mediaobject"><table border="0" summary="manufactured viewport for HTML img" cellspacing="0" cellpadding="0" width="261"><tr><td><img src="img/jpa-assoc-table.png"></td></tr></table></div><p> |
| You define join tables with the <code class="classname">JoinTable</code> annotation. |
| This annotation has the following properties: |
| </p><div class="itemizedlist"><ul type="disc"><li><p> |
| <code class="literal">String name</code>: 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. |
| </p></li><li><p> |
| <code class="literal">String catalog</code>: Table catalog. |
| </p></li><li><p> |
| <code class="literal">String schema</code>: Table schema. |
| </p></li><li><p> |
| <code class="literal">JoinColumn[] joinColumns</code>: Array of <code class="classname">JoinColumn |
| </code> showing how to associate join table records with the owning row in |
| the primary table. This property mirrors the <code class="literal">pkJoinColumns</code> |
| property of the <code class="classname"> SecondaryTable</code> annotation in |
| functionality. See <a href="jpa_overview_mapping_field.html#jpa_overview_mapping_secondary" title="8.2. Secondary Tables">Section 8.2, “ |
| Secondary Tables |
| ”</a> to |
| refresh your memory on secondary tables. |
| </p><p> |
| If this is a bidirectional relation (see |
| <a href="jpa_overview_meta_field.html#jpa_overview_meta_mappedby" title="2.10.1. Bidirectional Relations">Section 2.10.1, “ |
| Bidirectional Relations |
| ”</a> ), 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. |
| </p></li><li><p> |
| <code class="literal">JoinColumn[] inverseJoinColumns</code>: Array of <code class="classname"> |
| JoinColumns</code> 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 <a href="jpa_overview_mapping_field.html#jpa_overview_mapping_rel" title="8.4. Direct Relations">Section 8.4, “ |
| Direct Relations |
| ”</a> for a review of |
| direct relation mapping. |
| </p></li></ul></div><p> |
| <code class="literal">join-table</code> is the corresponding XML element. It has the same |
| attributes as the <code class="literal">table</code> element, but includes the ability to |
| nest <code class="literal">join-column</code> and <code class="literal">inverse-join-column</code> |
| elements as children. We have seen <code class="literal">join-column</code> elements |
| already; <code class="literal">inverse-join-column</code> elements have the same |
| attributes. |
| </p><p> |
| Here are the join table mappings for the diagram above. |
| </p><div class="example"><a name="jpa_overview_mapping_assoccollex"></a><p class="title"><b>Example 13.15. |
| Join Table Mapping |
| </b></p><div class="example-contents"><pre class="programlisting"> |
| package org.mag; |
| |
| @Entity |
| @Table(name="MAG") |
| public class Magazine { |
| |
| @Column(length=9) |
| @Id private String isbn; |
| @Id private String title; |
| |
| @OneToMany(...) |
| @OrderBy |
| @JoinTable(name="MAG_ARTS", |
| joinColumns={ |
| @JoinColumn(name="MAG_ISBN", referencedColumnName="ISBN"), |
| @JoinColumn(name="MAG_TITLE", referencedColumnName="TITLE") |
| }, |
| inverseJoinColumns=@JoinColumn(name="ART_ID", referencedColumnName="ID")) |
| private Collection<Article> articles; |
| |
| ... |
| } |
| |
| @Entity |
| @Table(name="ART") |
| public class Article { |
| |
| @Id private long id; |
| |
| @ManyToMany(cascade=CascadeType.PERSIST) |
| @OrderBy("lastName, firstName") |
| @JoinTable(name="ART_AUTHS", |
| joinColumns=@JoinColumn(name="ART_ID", referencedColumnName="ID"), |
| inverseJoinColumns=@JoinColumn(name="AUTH_ID", referencedColumnName="AID")) |
| private Collection<Author> authors; |
| |
| ... |
| } |
| |
| |
| package org.mag.pub; |
| |
| @Entity |
| @Table(name="AUTH") |
| public class Author { |
| |
| @Column(name="AID", columnDefinition="INTEGER64") |
| @Id private long id; |
| |
| ... |
| } |
| </pre><p> |
| The same metadata expressed in XML: |
| </p><pre class="programlisting"> |
| <entity class="org.mag.Magazine"> |
| <table name="MAG"/> |
| <attributes> |
| <id name="isbn"> |
| <column length="9"/> |
| </id> |
| <id name="title"/> |
| <one-to-many name="articles"> |
| <order-by/> |
| <join-table name="MAG_ARTS"> |
| <join-column name="MAG_ISBN" referenced-column-name="ISBN"/> |
| <join-column name="MAG_TITLE" referenced-column-name="TITLE"/> |
| <inverse-join-column name="ART_ID" referenced-column-name="ID"/> |
| </join-table> |
| </one-to-many> |
| ... |
| </attributes> |
| </entity> |
| <entity class="org.mag.Article"> |
| <table name="ART"/> |
| <attributes> |
| <id name="id"/> |
| <many-to-many name="authors"> |
| <order-by>lastName, firstName</order-by> |
| <join-table name="ART_AUTHS"> |
| <join-column name="ART_ID" referenced-column-name="ID"/> |
| <inverse-join-column name="AUTH_ID" referenced-column-name="AID"/> |
| </join-table> |
| <cascade> |
| <cascade-persist/> |
| </cascade> |
| </many-to-many> |
| ... |
| </attributes> |
| </entity> |
| <entity class="org.mag.pub.Author"> |
| <table name="AUTH"/> |
| <attributes> |
| <id name="id"> |
| <column name="AID" column-definition="INTEGER64"/> |
| </id> |
| ... |
| </attributes> |
| </entity> |
| </pre></div></div><br class="example-break"></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="jpa_overview_mapping_bidi"></a>8.6. |
| Bidirectional Mapping |
| </h3></div></div></div><a class="indexterm" name="d0e13900"></a><p> |
| <a href="jpa_overview_meta_field.html#jpa_overview_meta_mappedby" title="2.10.1. Bidirectional Relations">Section 2.10.1, “ |
| Bidirectional Relations |
| ”</a> 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 <code class="literal"> |
| mappedBy</code> property of the other field's metadata annotation or the |
| corresponding <code class="literal">mapped-by</code> XML attribute to refer to the mapped |
| field. Look for this pattern in these bidirectional relations as you peruse the |
| complete mappings below: |
| </p><div class="itemizedlist"><ul type="disc"><li><p> |
| <code class="literal">Magazine.publisher</code> and <code class="literal">Company.mags</code>. |
| </p></li><li><p> |
| <code class="literal">Article.authors</code> and <code class="literal">Author.articles</code>. |
| </p></li></ul></div></div><div class="section" lang="en"><div class="titlepage"><div><div><h3 class="title"><a name="jpa_overview_mapping_map"></a>8.7. |
| Map Mapping |
| </h3></div></div></div><a class="indexterm" name="d0e13937"></a><a class="indexterm" name="d0e13942"></a><p> |
| 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 <a href="jpa_overview_mapping_field.html#jpa_overview_mapping_assoccoll" title="8.5. Join Table">join |
| tables</a> or <a href="jpa_overview_mapping_field.html#jpa_overview_mapping_bidi" title="8.6. Bidirectional Mapping">bidirectional |
| relations</a>. The only additions are the <code class="classname">MapKey</code> |
| annotation and <code class="literal">map-key</code> element to declare the key field. We |
| covered these additions in <a href="jpa_overview_meta_field.html#jpa_overview_meta_mapkey" title="2.14. Map Key">Section 2.14, “ |
| Map Key |
| ”</a>. |
| </p><div class="mediaobject"><table border="0" summary="manufactured viewport for HTML img" cellspacing="0" cellpadding="0" width="255"><tr><td><img src="img/jpa-map.png"></td></tr></table></div><p> |
| The example below maps <code class="classname">Subscription</code>'s map of <code class="classname"> |
| LineItem</code>s to the <code class="literal">SUB_ITEMS</code> join table. The key |
| for each map entry is the <code class="classname"> LineItem</code>'s <code class="literal">num |
| </code> field value. |
| </p><div class="example"><a name="jpa_overview_mapping_mapex"></a><p class="title"><b>Example 13.16. |
| Join Table Map Mapping |
| </b></p><div class="example-contents"><pre class="programlisting"> |
| package org.mag.subscribe; |
| |
| @Entity |
| @Table(name="SUB", schema="CNTRCT") |
| public class Subscription { |
| |
| @OneToMany(cascade={CascadeType.PERSIST,CascadeType.REMOVE}) |
| @MapKey(name="num") |
| @JoinTable(name="SUB_ITEMS", schema="CNTRCT", |
| joinColumns=@JoinColumn(name="SUB_ID"), |
| inverseJoinColumns=@JoinColumn(name="ITEM_ID")) |
| private Map<Long,LineItem> items; |
| |
| ... |
| |
| @Entity |
| @Table(name="LINE_ITEM", schema="CNTRCT") |
| public static class LineItem |
| extends Contract { |
| |
| private long num; |
| |
| ... |
| } |
| } |
| </pre><p> |
| The same metadata expressed in XML: |
| </p><pre class="programlisting"> |
| <entity class="org.mag.subscribe.Subscription"> |
| <table name="SUB" schema="CNTRCT"/> |
| <attributes> |
| ... |
| <one-to-many name="items"> |
| <map-key name="num"> |
| <join-table name="SUB_ITEMS" schema="CNTRCT"> |
| <join-column name="SUB_ID"/> |
| <inverse-join-column name="ITEM_ID"/> |
| </join-table> |
| <cascade> |
| <cascade-persist/> |
| <cascade-remove/> |
| </cascade> |
| </one-to-many> |
| ... |
| </attributes> |
| </entity> |
| <entity class="org.mag.subscribe.Subscription.LineItem"> |
| <table name="LINE_ITEM" schema="CNTRCT"/> |
| <attributes> |
| ... |
| <basic name="num"/> |
| ... |
| </attributes> |
| </entity> |
| </pre></div></div><br class="example-break"></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="jpa_overview_mapping_discrim.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="jpa_overview_mapping.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="jpa_overview_mapping_full.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">7. |
| Discriminator |
| </td><td width="20%" align="center"><a accesskey="h" href="manual.html">Home</a></td><td width="40%" align="right" valign="top"> 9. |
| The Complete Mappings |
| </td></tr></table></div></body></html> |