|  | <html><head> | 
|  | <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> | 
|  | <title>9.  The Complete Mappings</title><base href="display"><link rel="stylesheet" type="text/css" href="css/docbook.css"><meta name="generator" content="DocBook XSL-NS Stylesheets V1.76.1"><link rel="home" href="manual.html" title="Apache OpenJPA 2.2 User's Guide"><link rel="up" href="jpa_overview_mapping.html" title="Chapter 13.  Mapping Metadata"><link rel="prev" href="jpa_overview_mapping_field.html" title="8.  Field Mapping"><link rel="next" href="jpa_overview_conclusion.html" title="Chapter 14.  Conclusion"></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">9.  | 
|  | The Complete Mappings | 
|  | </th></tr><tr><td width="20%" align="left"><a accesskey="p" href="jpa_overview_mapping_field.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_conclusion.html">Next</a></td></tr></table><hr></div><div class="section" title="9.  The Complete Mappings"><div class="titlepage"><div><div><h2 class="title" style="clear: both" id="jpa_overview_mapping_full">9.  | 
|  | The Complete Mappings | 
|  | </h2></div></div></div> | 
|  |  | 
|  | <p> | 
|  | We began this chapter with the goal of mapping the following object model: | 
|  | </p> | 
|  | <div class="mediaobject"><table border="0" summary="manufactured viewport for HTML img" cellspacing="0" cellpadding="0" width="369"><tr><td><img src="img/jpa-meta-model.png"></td></tr></table></div> | 
|  | <p> | 
|  | That goal has now been met. In the course of explaining JPA's object-relational | 
|  | mapping metadata, we slowly built the requisite schema and mappings for the | 
|  | complete model. First, the database schema: | 
|  | </p> | 
|  | <div class="mediaobject"><table border="0" summary="manufactured viewport for HTML img" cellspacing="0" cellpadding="0" width="326"><tr><td><img src="img/jpa-data-model.png"></td></tr></table></div> | 
|  | <p> | 
|  | And finally, the complete entity mappings. We have trimmed the mappings to take | 
|  | advantage of JPA defaults where possible. | 
|  | </p> | 
|  | <div class="example"><a name="jpa_overview_mapping_fullex"></a><p class="title"><b>Example 13.17.  | 
|  | Full Entity Mappings | 
|  | </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; | 
|  |  | 
|  | @OneToOne(fetch=FetchType.LAZY, | 
|  | cascade={CascadeType.PERSIST,CascadeType.REMOVE}) | 
|  | @JoinColumn(name="COVER_ID") | 
|  | private Article coverArticle; | 
|  |  | 
|  | @OneToMany(cascade={CascadeType.PERSIST,CascadeType.REMOVE}) | 
|  | @OrderBy | 
|  | @JoinTable(name="MAG_ARTS", | 
|  | joinColumns={ | 
|  | @JoinColumn(name="MAG_ISBN", referencedColumnName="ISBN"), | 
|  | @JoinColumn(name="MAG_TITLE", referencedColumnName="TITLE") | 
|  | }, | 
|  | inverseJoinColumns=@JoinColumn(name="ART_ID")) | 
|  | private Collection<Article> articles; | 
|  |  | 
|  | @ManyToOne(fetch=FetchType.LAZY, cascade=CascadeType.PERSIST) | 
|  | @JoinColumn(name="PUB_ID") | 
|  | private Company publisher; | 
|  |  | 
|  | @Transient private byte[] data; | 
|  |  | 
|  |  | 
|  | ... | 
|  |  | 
|  | 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; | 
|  |  | 
|  | @ManyToMany(cascade=CascadeType.PERSIST) | 
|  | @OrderBy("lastName, firstName") | 
|  | @JoinTable(name="ART_AUTHS", | 
|  | joinColumns=@JoinColumn(name="ART_ID"), | 
|  | inverseJoinColumns=@JoinColumn(name="AUTH_ID")) | 
|  | private Collection<Author> authors; | 
|  |  | 
|  | ... | 
|  | } | 
|  |  | 
|  |  | 
|  | 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; | 
|  |  | 
|  | @Embedded | 
|  | @AttributeOverrides({ | 
|  | @AttributeOverride(name="street", column=@Column(name="STRT")), | 
|  | @AttributeOverride(name="city", column=@Column(name="ACITY")) | 
|  | }) | 
|  | private Address address; | 
|  |  | 
|  | @OneToMany(mappedBy="publisher", cascade=CascadeType.PERSIST) | 
|  | private Collection<Magazine> mags; | 
|  |  | 
|  | @OneToMany(cascade=CascadeType.PERSIST,CascadeType.REMOVE) | 
|  | @JoinTable(name="COMP_SUBS", | 
|  | joinColumns=@JoinColumn(name="COMP_ID"), | 
|  | inverseJoinColumns=@JoinColumn(name="SUB_ID")) | 
|  | private Collection<Subscription> subscriptions; | 
|  |  | 
|  | ... | 
|  | } | 
|  |  | 
|  | @Entity | 
|  | @Table(name="AUTH") | 
|  | public class Author { | 
|  |  | 
|  | @Id | 
|  | @GeneratedValue(strategy=GenerationType.TABLE, generator="AuthorGen") | 
|  | @TableGenerator(name="AuthorGen", tableName="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; | 
|  |  | 
|  | private Address address; | 
|  |  | 
|  | @ManyToMany(mappedBy="authors", cascade=CascadeType.PERSIST) | 
|  | private Collection<Article> arts; | 
|  |  | 
|  | ... | 
|  | } | 
|  |  | 
|  | @Embeddable | 
|  | public class Address { | 
|  |  | 
|  | private String street; | 
|  | private String city; | 
|  | @Column(columnDefinition="CHAR(2)") | 
|  | private String state; | 
|  | private String zip; | 
|  | } | 
|  |  | 
|  |  | 
|  | 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; | 
|  |  | 
|  | @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 { | 
|  |  | 
|  | @Column(name="COMM") | 
|  | private String comments; | 
|  |  | 
|  | private double price; | 
|  | private long num; | 
|  |  | 
|  | @ManyToOne | 
|  | @JoinColumns({ | 
|  | @JoinColumn(name="MAG_ISBN", referencedColumnName="ISBN"), | 
|  | @JoinColumn(name="MAG_TITLE", referencedColumnName="TITLE") | 
|  | }) | 
|  | private Magazine magazine; | 
|  | ... | 
|  | } | 
|  | } | 
|  |  | 
|  | @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 form: | 
|  | </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> | 
|  | <many-to-one name="publisher" fetch="LAZY"> | 
|  | <join-column name="PUB_ID"/> | 
|  | <cascade> | 
|  | <cascade-persist/> | 
|  | </cascade> | 
|  | </many-to-one> | 
|  | <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"/> | 
|  | </join-table> | 
|  | <cascade> | 
|  | <cascade-persist/> | 
|  | <cascade-remove/> | 
|  | </cascade> | 
|  | </one-to-many> | 
|  | <one-to-one name="coverArticle" fetch="LAZY"> | 
|  | <join-column name="COVER_ID"/> | 
|  | <cascade> | 
|  | <cascade-persist/> | 
|  | <cascade-remove/> | 
|  | </cascade> | 
|  | </one-to-one> | 
|  | <transient name="data"/> | 
|  | </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> | 
|  | <many-to-many name="articles"> | 
|  | <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> | 
|  | </many-to-many> | 
|  | </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> | 
|  | <version name="version"> | 
|  | <column name="VERS"/> | 
|  | </version> | 
|  | <one-to-many name="mags" mapped-by="publisher"> | 
|  | <cascade> | 
|  | <cascade-persist/> | 
|  | </cascade> | 
|  | </one-to-many> | 
|  | <one-to-many name="subscriptions"> | 
|  | <join-table name="COMP_SUBS"> | 
|  | <join-column name="COMP_ID"/> | 
|  | <inverse-join-column name="SUB_ID"/> | 
|  | </join-table> | 
|  | <cascade> | 
|  | <cascade-persist/> | 
|  | <cascade-remove/> | 
|  | </cascade> | 
|  | </one-to-many> | 
|  | <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> | 
|  | <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> | 
|  | <many-to-many name="arts" mapped-by="authors"> | 
|  | <cascade> | 
|  | <cascade-persist/> | 
|  | </cascade> | 
|  | </many-to-many> | 
|  | <embedded name="address"/> | 
|  | </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> | 
|  | <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="comments"> | 
|  | <column name="COMM"/> | 
|  | </basic> | 
|  | <basic name="price"/> | 
|  | <basic name="num"/> | 
|  | <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> | 
|  | <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> | 
|  | <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> | 
|  | </entity-mappings> | 
|  | </pre> | 
|  | </div></div><br class="example-break"> | 
|  | </div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="jpa_overview_mapping_field.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_conclusion.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">8.  | 
|  | Field Mapping | 
|  |  </td><td width="20%" align="center"><a accesskey="h" href="manual.html">Home</a></td><td width="40%" align="right" valign="top"> Chapter 14.  | 
|  | Conclusion | 
|  | </td></tr></table></div></body></html> |