alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Hibernate example source code file (collection_mapping.xml)

This example Hibernate source code file (collection_mapping.xml) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Hibernate tags/keywords

child, entity, entity, hibernate, id, java, java, parent, set, string, the, the, xml, xml

The Hibernate collection_mapping.xml source code

<?xml version="1.0" encoding="UTF-8"?>
<!--
  ~ Hibernate, Relational Persistence for Idiomatic Java
  ~
  ~ Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
  ~ indicated by the @author tags or express copyright attribution
  ~ statements applied by the authors.  All third-party contributions are
  ~ distributed under license by Red Hat Middleware LLC.
  ~
  ~ This copyrighted material is made available to anyone wishing to use, modify,
  ~ copy, or redistribute it subject to the terms and conditions of the GNU
  ~ Lesser General Public License, as published by the Free Software Foundation.
  ~
  ~ This program is distributed in the hope that it will be useful,
  ~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  ~ or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
  ~ for more details.
  ~
  ~ You should have received a copy of the GNU Lesser General Public License
  ~ along with this distribution; if not, write to:
  ~ Free Software Foundation, Inc.
  ~ 51 Franklin Street, Fifth Floor
  ~ Boston, MA  02110-1301  USA
  -->
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY % BOOK_ENTITIES SYSTEM "../HIBERNATE_-_Relational_Persistence_for_Idiomatic_Java.ent">
%BOOK_ENTITIES;
]>
<chapter id="collections">
  <title>Collection mapping

  <section id="collections-persistent" revision="3">
    <title>Persistent collections

    <para>Naturally Hibernate also allows to persist collections. These
    persistent collections can contain almost any other Hibernate type,
    including: basic types, custom types, components and references to other
    entities. The distinction between value and reference semantics is in this
    context very important. An object in a collection might be handled with
    "value" semantics (its life cycle fully depends on the collection owner),
    or it might be a reference to another entity with its own life cycle. In
    the latter case, only the "link" between the two objects is considered to
    be a state held by the collection.</para>

    <para>As a requirement persistent collection-valued fields must be
    declared as an interface type (see <xref
    linkend="example.collection.mapping.annotations" />). The actual interface
    might be <literal>java.util.Set,
    <literal>java.util.Collection,
    <literal>java.util.List, java.util.Map,
    <literal>java.util.SortedSet,
    <literal>java.util.SortedMap or anything you like ("anything you
    like" means you will have to write an implementation of
    <literal>org.hibernate.usertype.UserCollectionType).

    <para>Notice how in  was initialized with an instance of
    <literal>HashSet. This is the best way to initialize collection
    valued properties of newly instantiated (non-persistent) instances. When
    you make the instance persistent, by calling <literal>persist(),
    Hibernate will actually replace the <literal>HashSet with an
    instance of Hibernate's own implementation of <literal>Set. Be
    aware of the following error:</para>

    <example>
      <title>Hibernate uses its own collection implementations

      <programlisting role="JAVA">Cat cat = new DomesticCat();
Cat kitten = new DomesticCat();
....
Set kittens = new HashSet();
kittens.add(kitten);
cat.setKittens(kittens);
session.persist(cat);

kittens = cat.getKittens(); // Okay, kittens collection is a Set
(HashSet) cat.getKittens(); // Error!</programlisting>
    </example>

    <para>The persistent collections injected by Hibernate behave like
    <literal>HashMap, HashSet,
    <literal>TreeMap, TreeSet or
    <literal>ArrayList, depending on the interface type.

    <para>Collections instances have the usual behavior of value types. They
    are automatically persisted when referenced by a persistent object and are
    automatically deleted when unreferenced. If a collection is passed from
    one persistent object to another, its elements might be moved from one
    table to another. Two entities cannot share a reference to the same
    collection instance. Due to the underlying relational model,
    collection-valued properties do not support null value semantics.
    Hibernate does not distinguish between a null collection reference and an
    empty collection.</para>

    <note>
      <para>Use persistent collections the same way you use ordinary Java
      collections. However, ensure you understand the semantics of
      bidirectional associations (see <xref
      linkend="collections-bidirectional" />).</para>
    </note>
  </section>

  <section id="collections-mapping" revision="4">
    <title>How to map collections

    <para>Using annotations you can map Collections,
    <classname>Lists, Maps and
    <classname>Sets of associated entities using @OneToMany and
    @ManyToMany. For collections of a basic or embeddable type use
    @ElementCollection. In the simplest case a collection mapping looks like
    this:</para>

    <example id="example.collection.mapping.annotations">
      <title>Collection mapping using @OneToMany and @JoinColumn

      <programlisting role="JAVA">@Entity
public class Product {

    private String serialNumber;
    private Set<Part> parts = new HashSet<Part>();

    @Id
    public String getSerialNumber() { return serialNumber; }
    void setSerialNumber(String sn) { serialNumber = sn; }
   
    @OneToMany
    @JoinColumn(name="PART_ID")
    public Set<Part> getParts() { return parts; }
    void setParts(Set parts) { this.parts = parts; }
}


@Entity
public class Part {
   ...
}</programlisting>
    </example>

    <para>Product describes a unidirectional relationship with Part using the
    join column PART_ID. In this unidirectional one to many scenario you can
    also use a join table as seen in <xref
    linkend="example-one-to-many-with-join-table" />.</para>

    <example id="example-one-to-many-with-join-table">
      <title id="example-one-to-many-with-join-table">Collection mapping using
      @OneToMany and @JoinTable</title>

      <programlisting role="JAVA">@Entity
public class Product {

    private String serialNumber;
    private Set<Part> parts = new HashSet<Part>();

    @Id
    public String getSerialNumber() { return serialNumber; }
    void setSerialNumber(String sn) { serialNumber = sn; }
   
    @OneToMany
    @JoinTable(
            name="PRODUCT_PARTS",
            joinColumns = @JoinColumn( name="PRODUCT_ID"),
            inverseJoinColumns = @JoinColumn( name="PART_ID")
    )
    public Set<Part> getParts() { return parts; }
    void setParts(Set parts) { this.parts = parts; }
}


@Entity
public class Part {
   ...
}</programlisting>
    </example>

    <para>Without describing any physical mapping (no
    <classname>@JoinColumn or @JoinTable),
    a unidirectional one to many with join table is used. The table name is
    the concatenation of the owner table name, _, and the other side table
    name. The foreign key name(s) referencing the owner table is the
    concatenation of the owner table, _, and the owner primary key column(s)
    name. The foreign key name(s) referencing the other side is the
    concatenation of the owner property name, _, and the other side primary
    key column(s) name. A unique constraint is added to the foreign key
    referencing the other side table to reflect the one to many.</para>

    <para>Lets have a look now how collections are mapped using Hibernate
    mapping files. In this case the first step is to chose the right mapping
    element. It depends on the type of interface. For example, a
    <literal><set> element is used for mapping properties of
    type <literal>Set.

    <example floatstyle="" id="example.collections.set">
      <title>Mapping a Set using <set>

      <programlisting role="JAVA"><class name="Product">
    <id name="serialNumber" column="productSerialNumber"/>
    <set name="parts">
        <key column="productSerialNumber" not-null="true"/>
        <one-to-many class="Part"/>
    </set>
</class></programlisting>
    </example>

    <para>In  a
    <emphasis>one-to-many association links the
    <literal>Product and Part entities. This
    association requires the existence of a foreign key column and possibly an
    index column to the <literal>Part table. This mapping loses
    certain semantics of normal Java collections:</para>

    <itemizedlist spacing="compact">
      <listitem>
        <para>An instance of the contained entity class cannot belong to more
        than one instance of the collection.</para>
      </listitem>

      <listitem>
        <para>An instance of the contained entity class cannot appear at more
        than one value of the collection index.</para>
      </listitem>
    </itemizedlist>

    <para>Looking closer at the used <one-to-many>
    tag we see that it has the following options.</para>

    <example>
      <title>options of <one-to-many> element

      <programlistingco role="XML">
        <areaspec>
          <area coords="2" id="onetomany1" />

          <area coords="3" id="onetomany2" />

          <area coords="4" id="onetomany3" />
        </areaspec>

        <programlisting><one-to-many
        class="ClassName"
        not-found="ignore|exception"
        entity-name="EntityName"
        node="element-name"
        embed-xml="true|false"
    /></programlisting>

        <calloutlist>
          <callout arearefs="onetomany1">
            <para>class (required): the name of the
            associated class.</para>
          </callout>

          <callout arearefs="onetomany2">
            <para>not-found (optional - defaults to
            <literal>exception): specifies how cached identifiers
            that reference missing rows will be handled.
            <literal>ignore will treat a missing row as a null
            association.</para>
          </callout>

          <callout arearefs="onetomany3">
            <para>entity-name (optional): the entity name
            of the associated class, as an alternative to
            <literal>class.
          </callout>
        </calloutlist>
      </programlistingco>
    </example>

    <para>The <one-to-many> element does not need to
    declare any columns. Nor is it necessary to specify the
    <literal>table name anywhere.

    <warning>
      <para>If the foreign key column of a
      <literal><one-to-many> association is declared
      <literal>NOT NULL, you must declare the
      <literal><key> mapping
      <literal>not-null="true" or use a bidirectional
      association</emphasis> with the collection mapping marked
      <literal>inverse="true". See 
    </warning>

    <para>Apart from the <set> tag as shown in , <map>,
    <literal><bag>, <array> and
    <literal><primitive-array> mapping elements. The
    <literal><map> element is representative:

    <example>
      <title>Elements of the <map> mapping

      <programlistingco role="XML">
        <areaspec>
          <area coords="2" id="mappingcollection1" />

          <area coords="3" id="mappingcollection2" />

          <area coords="4" id="mappingcollection3" />

          <area coords="5" id="mappingcollection4" />

          <area coords="6" id="mappingcollection5" />

          <area coords="7" id="mappingcollection6" />

          <area coords="8" id="mappingcollection7" />

          <area coords="9" id="mappingcollection8" />

          <area coords="10" id="mappingcollection9" />

          <area coords="11" id="mappingcollection10" />

          <area coords="12" id="mappingcollection11" />

          <area coords="13" id="mappingcollection12" />

          <area coords="14" id="mappingcollection13" />

          <area coords="15" id="mappingcollection14" />
        </areaspec>

        <programlisting><map
    name="propertyName"
    table="table_name"
    schema="schema_name"
    lazy="true|extra|false"
    inverse="true|false"
    cascade="all|none|save-update|delete|all-delete-orphan|delete-orphan"
    sort="unsorted|natural|comparatorClass"
    order-by="column_name asc|desc"
    where="arbitrary sql where condition"
    fetch="join|select|subselect"
    batch-size="N"
    access="field|property|ClassName"
    optimistic-lock="true|false"
    mutable="true|false"
    node="element-name|."
    embed-xml="true|false"
>

    <key .... />
    <map-key .... />
    <element .... />
</map></programlisting>

        <calloutlist>
          <callout arearefs="mappingcollection1">
            <para>name: the collection property name
          </callout>

          <callout arearefs="mappingcollection2">
            <para>table (optional - defaults to property
            name): the name of the collection table. It is not used for
            one-to-many associations.</para>
          </callout>

          <callout arearefs="mappingcollection3">
            <para>schema (optional): the name of a table
            schema to override the schema declared on the root element</para>
          </callout>

          <callout arearefs="mappingcollection4">
            <para>lazy (optional - defaults to
            <literal>true): disables lazy fetching and specifies
            that the association is always eagerly fetched. It can also be
            used to enable "extra-lazy" fetching where most operations do not
            initialize the collection. This is suitable for large
            collections.</para>
          </callout>

          <callout arearefs="mappingcollection5">
            <para>inverse (optional - defaults to
            <literal>false): marks this collection as the "inverse"
            end of a bidirectional association.</para>
          </callout>

          <callout arearefs="mappingcollection6">
            <para>cascade (optional - defaults to
            <literal>none): enables operations to cascade to child
            entities.</para>
          </callout>

          <callout arearefs="mappingcollection7">
            <para>sort (optional): specifies a sorted
            collection with <literal>natural sort order or a given
            comparator class.</para>
          </callout>

          <callout arearefs="mappingcollection8">
            <para>order-by (optional): specifies a table
            column or columns that define the iteration order of the
            <literal>Map, Set or bag, together
            with an optional <literal>asc or
            <literal>desc.
          </callout>

          <callout arearefs="mappingcollection9">
            <para>where (optional): specifies an arbitrary
            SQL <literal>WHERE condition that is used when
            retrieving or removing the collection. This is useful if the
            collection needs to contain only a subset of the available
            data.</para>
          </callout>

          <callout arearefs="mappingcollection10">
            <para>fetch (optional, defaults to
            <literal>select): chooses between outer-join fetching,
            fetching by sequential select, and fetching by sequential
            subselect.</para>
          </callout>

          <callout arearefs="mappingcollection11">
            <para>batch-size (optional, defaults to
            <literal>1): specifies a "batch size" for lazily
            fetching instances of this collection.</para>
          </callout>

          <callout arearefs="mappingcollection12">
            <para>access (optional - defaults to
            <literal>property): the strategy Hibernate uses for
            accessing the collection property value.</para>
          </callout>

          <callout arearefs="mappingcollection13">
            <para>optimistic-lock (optional - defaults to
            <literal>true): specifies that changes to the state of
            the collection results in increments of the owning entity's
            version. For one-to-many associations you may want to disable this
            setting.</para>
          </callout>

          <callout arearefs="mappingcollection14">
            <para>mutable (optional - defaults to
            <literal>true): a value of false
            specifies that the elements of the collection never change. This
            allows for minor performance optimization in some cases.</para>
          </callout>
        </calloutlist>
      </programlistingco>
    </example>

    <para>After exploring the basic mapping of collections in the preceding
    paragraphs we will now focus details like physical mapping considerations,
    indexed collections and collections of value types.</para>

    <section id="collections-foreignkeys">
      <title>Collection foreign keys

      <para>On the database level collection instances are distinguished by
      the foreign key of the entity that owns the collection. This foreign key
      is referred to as the <emphasis>collection key column, or
      columns, of the collection table. The collection key column is mapped by
      the <literal>@JoinColumn annotation respectively the
      <literal><key> XML element.

      <para>There can be a nullability constraint on the foreign key column.
      For most collections, this is implied. For unidirectional one-to-many
      associations, the foreign key column is nullable by default, so you may
      need to specify</para>

      <programlisting role="Java">@JoinColumn(nullable=false)

      <para>or

      <programlisting role="XML"><key column="productSerialNumber" not-null="true"/>

      <para>The foreign key constraint can use ON DELETE
      CASCADE</literal>. In XML this can be expressed via:

      <programlisting role="XML"><key column="productSerialNumber" on-delete="cascade"/>

      <para>In annotations the Hibernate specific annotation @OnDelete has to
      be used.</para>

      <programlisting role="Java">@OnDelete(action=OnDeleteAction.CASCADE)

      <para>See  for more information
      about the <literal><key> element.
    </section>

    <section id="collections-indexed">
      <title id="section.indexed.collections">Indexed collections

      <para>In the following paragraphs we have a closer at the indexed
      collections <classname>List and Map
      how the their index can be mapped in Hibernate.</para>

      <section>
        <title>Lists

        <para>Lists can be mapped in two different ways:

        <itemizedlist>
          <listitem>
            <para>as ordered lists, where the order is not materialized in the
            database</para>
          </listitem>

          <listitem>
            <para>as indexed lists, where the order is materialized in the
            database</para>
          </listitem>
        </itemizedlist>

        <para>To order lists in memory, add
        <literal>@javax.persistence.OrderBy to your property. This
        annotation takes as parameter a list of comma separated properties (of
        the target entity) and orders the collection accordingly (eg
        <code>firstname asc, age desc), if the string is empty, the
        collection will be ordered by the primary key of the target
        entity.</para>

        <example>
          <title>Ordered lists using @OrderBy

          <programlisting language="JAVA" role="JAVA">@Entity
public class Customer {
   @Id @GeneratedValue public Integer getId() { return id; }
   public void setId(Integer id) { this.id = id; }
   private Integer id;

   @OneToMany(mappedBy="customer")
   @OrderBy("number")
   public List<Order> getOrders() { return orders; }
   public void setOrders(List<Order> orders) { this.orders = orders; }
   private List<Order> orders;
}

@Entity
public class Order {
   @Id @GeneratedValue public Integer getId() { return id; }
   public void setId(Integer id) { this.id = id; }
   private Integer id;

   public String getNumber() { return number; }
   public void setNumber(String number) { this.number = number; }
   private String number;

   @ManyToOne
   public Customer getCustomer() { return customer; }
   public void setCustomer(Customer customer) { this.customer = customer; }
   private Customer number;
}

-- Table schema
|-------------| |----------|
| Order       | | Customer |
|-------------| |----------|
| id          | | id       |
| number      | |----------| 
| customer_id |
|-------------|</programlisting>
        </example>

        <para>To store the index value in a dedicated column, use the
        <classname>@javax.persistence.OrderColumn annotation on
        your property. This annotations describes the column name and
        attributes of the column keeping the index value. This column is
        hosted on the table containing the association foreign key. If the
        column name is not specified, the default is the name of the
        referencing property, followed by underscore, followed by
        <literal>ORDER (in the following example, it would be
        <literal>orders_ORDER).

        <example>
          <title>Explicit index column using
          <classname>@OrderColumn

          <programlisting language="JAVA" role="JAVA">@Entity
public class Customer {
   @Id @GeneratedValue public Integer getId() { return id; }
   public void setId(Integer id) { this.id = id; }
   private Integer id;

   @OneToMany(mappedBy="customer")
   @OrderColumn(name="orders_index")
   public List<Order> getOrders() { return orders; }
   public void setOrders(List<Order> orders) { this.orders = orders; }
   private List<Order> orders;
}

@Entity
public class Order {
   @Id @GeneratedValue public Integer getId() { return id; }
   public void setId(Integer id) { this.id = id; }
   private Integer id;

   public String getNumber() { return number; }
   public void setNumber(String number) { this.number = number; }
   private String number;

   @ManyToOne
   public Customer getCustomer() { return customer; }
   public void setCustomer(Customer customer) { this.customer = customer; }
   private Customer number;
}

-- Table schema
|--------------| |----------|
| Order        | | Customer |
|--------------| |----------|
| id           | | id       |
| number       | |----------| 
| customer_id  |
| orders_order |
|--------------|</programlisting>
        </example>

        <note>
          <para>We recommend you to convert the legacy
          @org.hibernate.annotations.IndexColumn</classname> usages to
          <classname>@OrderColumn unless you are making use of the
          base property. The <literal>base property lets you define
          the index value of the first element (aka as base index). The usual
          value is <literal>0 or 1. The default
          is 0 like in Java.</para>
        </note>

        <para>Looking again at the Hibernate mapping file equivalent, the
        index of an array or list is always of type <literal>integer
        and is mapped using the <literal><list-index> element.
        The mapped column contains sequential integers that are numbered from
        zero by default.</para>

        <example>
          <title>index-list element for indexed collections in xml
          mapping</title>

          <programlistingco role="XML">
            <areaspec>
              <area coords="2" id="index1" />

              <area coords="3" id="index2" />
            </areaspec>

            <programlisting><list-index
        column="column_name"
        base="0|1|..."/></programlisting>

            <calloutlist>
              <callout arearefs="index1">
                <para>column_name (required): the name of
                the column holding the collection index values.</para>
              </callout>

              <callout arearefs="index1">
                <para>base (optional - defaults to
                <literal>0): the value of the index column that
                corresponds to the first element of the list or array.</para>
              </callout>
            </calloutlist>
          </programlistingco>
        </example>

        <para>If your table does not have an index column, and you still wish
        to use <literal>List as the property type, you can map the
        property as a Hibernate <emphasis><bag>. A bag does
        not retain its order when it is retrieved from the database, but it
        can be optionally sorted or ordered.</para>
      </section>

      <section>
        <title>Maps

        <para>The question with Maps is where the key
        value is stored. There are everal options. Maps can borrow their keys
        from one of the associated entity properties or have dedicated columns
        to store an explicit key.</para>

        <para>To use one of the target entity property as a key of the map,
        use <literal>@MapKey(name="myProperty"), where
        <literal>myProperty is a property name in the target entity.
        When using <literal>@MapKey without the name attribuate, the
        target entity primary key is used. The map key uses the same column as
        the property pointed out. There is no additional column defined to
        hold the map key, because the map key represent a target property. Be
        aware that once loaded, the key is no longer kept in sync with the
        property. In other words, if you change the property value, the key
        will not change automatically in your Java model.</para>

        <example>
          <title>Use of target entity property as map key via
          <classname>@MapKey

          <programlisting language="JAVA" role="JAVA">@Entity
public class Customer {
   @Id @GeneratedValue public Integer getId() { return id; }
   public void setId(Integer id) { this.id = id; }
   private Integer id;

   @OneToMany(mappedBy="customer")
   @MapKey(name="number")
   public Map<String,Order> getOrders() { return orders; }
   public void setOrders(Map<String,Order> order) { this.orders = orders; }
   private Map<String,Order> orders;
}

@Entity
public class Order {
   @Id @GeneratedValue public Integer getId() { return id; }
   public void setId(Integer id) { this.id = id; }
   private Integer id;

   public String getNumber() { return number; }
   public void setNumber(String number) { this.number = number; }
   private String number;

   @ManyToOne
   public Customer getCustomer() { return customer; }
   public void setCustomer(Customer customer) { this.customer = customer; }
   private Customer number;
}

-- Table schema
|-------------| |----------|
| Order       | | Customer |
|-------------| |----------|
| id          | | id       |
| number      | |----------| 
| customer_id |
|-------------|</programlisting>
        </example>

        <para>Alternatively the map key is mapped to a dedicated column or
        columns. In order to customize the mapping use one of the following
        annotations:</para>

        <itemizedlist>
          <listitem>
            <para>@MapKeyColumn if the map key is a
            basic type. If you don't specify the column name, the name of the
            property followed by underscore followed by <literal>KEY
            is used (for example <literal>orders_KEY).
          </listitem>

          <listitem>
            <para>@MapKeyEnumerated /
            <classname>@MapKeyTemporal if the map key type is
            respectively an enum or a <classname>Date.
          </listitem>

          <listitem>
            <para>@MapKeyJoinColumn/@MapKeyJoinColumns
            if the map key type is another entity.</para>
          </listitem>

          <listitem>
            <para>@AttributeOverride/@AttributeOverrides
            when the map key is a embeddable object. Use
            <literal>key. as a prefix for your embeddable object
            property names.</para>
          </listitem>
        </itemizedlist>

        <para>You can also use @MapKeyClass to define
        the type of the key if you don't use generics.</para>

        <example>
          <title>Map key as basic type using
          <classname>@MapKeyColumn

          <programlisting language="JAVA" role="JAVA">@Entity
public class Customer {
   @Id @GeneratedValue public Integer getId() { return id; }
   public void setId(Integer id) { this.id = id; }
   private Integer id;

   @OneToMany @JoinTable(name="Cust_Order")
   @MapKeyColumn(name="orders_number")
   public Map<String,Order> getOrders() { return orders; }
   public void setOrders(Map<String,Order> orders) { this.orders = orders; }
   private Map<String,Order> orders;
}

@Entity
public class Order {
   @Id @GeneratedValue public Integer getId() { return id; }
   public void setId(Integer id) { this.id = id; }
   private Integer id;

   public String getNumber() { return number; }
   public void setNumber(String number) { this.number = number; }
   private String number;

   @ManyToOne
   public Customer getCustomer() { return customer; }
   public void setCustomer(Customer customer) { this.customer = customer; }
   private Customer number;
}

-- Table schema
|-------------| |----------| |---------------|
| Order       | | Customer | | Cust_Order    |
|-------------| |----------| |---------------|
| id          | | id       | | customer_id   |
| number      | |----------| | order_id      |
| customer_id |              | orders_number |
|-------------|              |---------------|</programlisting>
        </example>

        <note>
          <para>We recommend you to migrate from
          <classname>@org.hibernate.annotations.MapKey /
          <classname>@org.hibernate.annotation.MapKeyManyToMany to
          the new standard approach described above</para>
        </note>

        <para>Using Hibernate mapping files there exists equivalent concepts
        to the descibed annotations. You have to use
        <literal><map-key>,
        <literal><map-key-many-to-many> and
        <literal><composite-map-key>.
        <literal><map-key> is used for any basic type,
        <literal><map-key-many-to-many> for an entity
        reference and <literal><composite-map-key> for a
        composite type.</para>

        <example>
          <title>map-key xml mapping element

          <programlistingco role="XML">
            <areaspec>
              <area coords="2" id="mapkey1" />

              <area coords="3" id="mapkey2" />

              <area coords="4" id="mapkey3" />
            </areaspec>

            <programlisting><map-key
        column="column_name"
        formula="any SQL expression"
        type="type_name"
        node="@attribute-name"
        length="N"/></programlisting>

            <calloutlist>
              <callout arearefs="mapkey1">
                <para>column (optional): the name of the
                column holding the collection index values.</para>
              </callout>

              <callout arearefs="mapkey2">
                <para>formula (optional): a SQL formula
                used to evaluate the key of the map.</para>
              </callout>

              <callout arearefs="mapkey3">
                <para>type (required): the type of the map
                keys.</para>
              </callout>
            </calloutlist>
          </programlistingco>
        </example>

        <example>
          <title>map-key-many-to-many

          <programlistingco role="XML">
            <areaspec>
              <area coords="2" id="indexmanytomany1" />

              <area coords="3" id="indexmanytomany2" />

              <area coords="3" id="indexmanytomany3" />
            </areaspec>

            <programlisting><map-key-many-to-many
        column="column_name"
        formula="any SQL expression"
        class="ClassName"
/></programlisting>

            <calloutlist>
              <callout arearefs="indexmanytomany1">
                <para>column (optional): the name of the
                foreign key column for the collection index values.</para>
              </callout>

              <callout arearefs="indexmanytomany2">
                <para>formula (optional): a SQ formula used
                to evaluate the foreign key of the map key.</para>
              </callout>

              <callout arearefs="indexmanytomany3">
                <para>class (required): the entity class
                used as the map key.</para>
              </callout>
            </calloutlist>
          </programlistingco>
        </example>
      </section>
    </section>

    <section id="collections-ofvalues" revision="2">
      <title>Collections of basic types and embeddable objects

      <para>In some situations you don't need to associate two entities but
      simply create a collection of basic types or embeddable objects. Use the
      <classname>@ElementCollection for this case.

      <example>
        <title>Collection of basic types mapped via
        <classname>@ElementCollection

        <programlisting language="JAVA" role="JAVA">@Entity
public class User {
   [...]
   public String getLastname() { ...}

   @ElementCollection
   @CollectionTable(name="Nicknames", joinColumns=@JoinColumn(name="user_id"))
   @Column(name="nickname")
   public Set<String> getNicknames() { ... } 
}</programlisting>
      </example>

      <para>The collection table holding the collection data is set using the
      <classname>@CollectionTable annotation. If omitted the
      collection table name defaults to the concatenation of the name of the
      containing entity and the name of the collection attribute, separated by
      an underscore. In our example, it would be
      <literal>User_nicknames.

      <para>The column holding the basic type is set using the
      <classname>@Column annotation. If omitted, the column name
      defaults to the property name: in our example, it would be
      <literal>nicknames.

      <para>But you are not limited to basic types, the collection type can be
      any embeddable object. To override the columns of the embeddable object
      in the collection table, use the
      <classname>@AttributeOverride annotation.

      <example>
        <title>@ElementCollection for embeddable objects

        <programlisting language="JAVA" role="JAVA">@Entity
public class User {
   [...]
   public String getLastname() { ...}

   @ElementCollection
   @CollectionTable(name="Addresses", joinColumns=@JoinColumn(name="user_id"))
   @AttributeOverrides({
      @AttributeOverride(name="street1", column=@Column(name="fld_street"))
   })
   public Set<Address> getAddresses() { ... } 
}

@Embeddable
public class Address {
   public String getStreet1() {...}
   [...]
}</programlisting>
      </example>

      <para>Such an embeddable object cannot contains a collection
      itself.</para>

      <note>
        <para>in @AttributeOverride, you must use the
        <literal>value. prefix to override properties of the
        embeddable object used in the map value and the
        <literal>key. prefix to override properties of the
        embeddable object used in the map key.</para>

        <programlisting language="JAVA" role="JAVA">@Entity
public class User {
   @ElementCollection
   @AttributeOverrides({
      @AttributeOverride(name="key.street1", column=@Column(name="fld_street")),
      @AttributeOverride(name="value.stars", column=@Column(name="fld_note"))
   })
   public Map<Address,Rating> getFavHomes() { ... }</programlisting>
      </note>

      <note>
        <para>We recommend you to migrate from
        <classname>@org.hibernate.annotations.CollectionOfElements
        to the new <classname>@ElementCollection
        annotation.</para>
      </note>

      <para>Using the mapping file approach a collection of values is mapped
      using the <literal><element> tag. For example:

      <example>
        <title><element> tag for collection values using mapping
        files</title>

        <programlistingco role="XML">
          <areaspec>
            <area coords="2" id="element1b" />

            <area coords="3" id="element2b" />

            <area coords="4" id="element3b" />
          </areaspec>

          <programlisting><element
        column="column_name"
        formula="any SQL expression"
        type="typename"
        length="L"
        precision="P"
        scale="S"
        not-null="true|false"
        unique="true|false"
        node="element-name"
/></programlisting>

          <calloutlist>
            <callout arearefs="element1b">
              <para>column (optional): the name of the
              column holding the collection element values.</para>
            </callout>

            <callout arearefs="element2b">
              <para>formula (optional): an SQL formula used
              to evaluate the element.</para>
            </callout>

            <callout arearefs="element3b">
              <para>type (required): the type of the
              collection element.</para>
            </callout>
          </calloutlist>
        </programlistingco>
      </example>
    </section>
  </section>

  <section id="collections-advancedmappings">
    <title>Advanced collection mappings

    <section id="collections-sorted" revision="2">
      <title id="section.sorted.collections">Sorted collections

      <para>Hibernate supports collections implementing
      <literal>java.util.SortedMap and
      <literal>java.util.SortedSet. With annotations you declare a
      sort comparator using <literal>@Sort. You chose between the
      comparator types unsorted, natural or custom. If you want to use your
      own comparator implementation, you'll also have to specify the
      implementation class using the <literal>comparator attribute.
      Note that you need to use either a <classname>SortedSet or a
      <classname>SortedMap interface.

      <example>
        <title>Sorted collection with @Sort

        <programlisting language="JAVA" role="JAVA">@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
@JoinColumn(name="CUST_ID")
@Sort(type = SortType.COMPARATOR, comparator = TicketComparator.class)
public SortedSet<Ticket> getTickets() {
    return tickets;
}</programlisting>
      </example>

      <para>Using Hibernate mapping files you specify a comparator in the
      mapping file with <literal><sort>:

      <example>
        <title>Sorted collection using xml mapping

        <programlisting role="XML"><set name="aliases"
            table="person_aliases" 
            sort="natural">
    <key column="person"/>
    <element column="name" type="string"/>
</set>

<map name="holidays" sort="my.custom.HolidayComparator">
    <key column="year_id"/>
    <map-key column="hol_name" type="string"/>
    <element column="hol_date" type="date"/>
</map></programlisting>
      </example>

      <para>Allowed values of the sort attribute are
      <literal>unsorted, natural and the name of
      a class implementing <literal>java.util.Comparator.

      <tip>
        <para>Sorted collections actually behave like
        <literal>java.util.TreeSet or
        <literal>java.util.TreeMap.
      </tip>

      <para>If you want the database itself to order the collection elements,
      use the <literal>order-by attribute of set,
      <literal>bag or map mappings. This solution
      is implemented using <literal>LinkedHashSet or
      <literal>LinkedHashMap and performs the ordering in the SQL
      query and not in the memory.</para>

      <example>
        <title>Sorting in database using order-by

        <programlisting role="XML"><set name="aliases" table="person_aliases" order-by="lower(name) asc">
    <key column="person"/>
    <element column="name" type="string"/>
</set>

<map name="holidays" order-by="hol_date, hol_name">
    <key column="year_id"/>
    <map-key column="hol_name" type="string"/>
    <element column="hol_date type="date"/>
</map></programlisting>
      </example>

      <note>
        <title>Note

        <para>The value of the order-by attribute is an SQL
        ordering, not an HQL ordering.</para>
      </note>

      <para>Associations can even be sorted by arbitrary criteria at runtime
      using a collection <literal>filter():

      <example>
        <title>Sorting via a query filter

        <programlisting role="JAVA">sortedUsers = s.createFilter( group.getUsers(), "order by this.name" ).list();
      </example>
    </section>

    <section id="collections-bidirectional" revision="1">
      <title>Bidirectional associations

      <para>A bidirectional association allows navigation
      from both "ends" of the association. Two kinds of bidirectional
      association are supported: <variablelist>
          <varlistentry>
            <term>one-to-many

            <listitem>
              <para>set or bag valued at one end and single-valued at the
              other</para>
            </listitem>
          </varlistentry>

          <varlistentry>
            <term>many-to-many

            <listitem>
              <para>set or bag valued at both ends
            </listitem>
          </varlistentry>
        </variablelist>

      <para>Often there exists a many to one association which is the owner
      side of a bidirectional relationship. The corresponding one to many
      association is in this case annotated by
      <literal>@OneToMany(mappedBy=...)

      <example>
        <title>Bidirectional one to many with many to one side as association
        owner</title>

        <programlisting language="JAVA" role="JAVA">@Entity
public class Troop {
    @OneToMany(mappedBy="troop")
    public Set<Soldier> getSoldiers() {
    ...
}

@Entity
public class Soldier {
    @ManyToOne
    @JoinColumn(name="troop_fk")
    public Troop getTroop() {
    ...
}           </programlisting>
      </example>

      <para>Troop has a bidirectional one to many
      relationship with <literal>Soldier through the
      <literal>troop property. You don't have to (must not) define
      any physical mapping in the <literal>mappedBy side.

      <para>To map a bidirectional one to many, with the one-to-many side as
      the owning side, you have to remove the <literal>mappedBy
      element and set the many to one <literal>@JoinColumn as
      insertable and updatable to false. This solution is not optimized and
      will produce additional UPDATE statements.</para>

      <example>
        <title>Bidirectional associtaion with one to many side as
        owner</title>

        <programlisting language="JAVA" role="JAVA">@Entity
public class Troop {
    @OneToMany
    @JoinColumn(name="troop_fk") //we need to duplicate the physical information
    public Set<Soldier> getSoldiers() {
    ...
}

@Entity
public class Soldier {
    @ManyToOne
    @JoinColumn(name="troop_fk", insertable=false, updatable=false)
    public Troop getTroop() {
    ...
}</programlisting>
      </example>

      <para>How does the mappping of a bidirectional mapping look like in
      Hibernate mapping xml? There you define a bidirectional one-to-many
      association by mapping a one-to-many association to the same table
      column(s) as a many-to-one association and declaring the many-valued end
      <literal>inverse="true".

      <example>
        <title>Bidirectional one to many via Hibernate mapping files

        <programlisting role="XML"><class name="Parent">
    <id name="id" column="parent_id"/>
    ....
    <set name="children" inverse="true">
        <key column="parent_id"/>
        <one-to-many class="Child"/>
    </set>
</class>

<class name="Child">
    <id name="id" column="child_id"/>
    ....
    <many-to-one name="parent" 
        class="Parent" 
        column="parent_id"
        not-null="true"/>
</class></programlisting>
      </example>

      <para>Mapping one end of an association with
      <literal>inverse="true" does not affect the operation of
      cascades as these are orthogonal concepts.</para>

      <para>A many-to-many association is defined logically using the
      <literal>@ManyToMany annotation. You also have to describe the
      association table and the join conditions using the
      <literal>@JoinTable annotation. If the association is
      bidirectional, one side has to be the owner and one side has to be the
      inverse end (ie. it will be ignored when updating the relationship
      values in the association table):</para>

      <example>
        <title>Many to many association via @ManyToMany

        <programlisting language="JAVA" role="JAVA">@Entity
public class Employer implements Serializable {
    @ManyToMany(
        targetEntity=org.hibernate.test.metadata.manytomany.Employee.class,
        cascade={CascadeType.PERSIST, CascadeType.MERGE}
    )
    @JoinTable(
        name="EMPLOYER_EMPLOYEE",
        joinColumns=@JoinColumn(name="EMPER_ID"),
        inverseJoinColumns=@JoinColumn(name="EMPEE_ID")
    )
    public Collection getEmployees() {
        return employees;
    }
    ...
}              </programlisting>

        <programlisting language="JAVA" role="JAVA">@Entity
public class Employee implements Serializable {
    @ManyToMany(
        cascade = {CascadeType.PERSIST, CascadeType.MERGE},
        mappedBy = "employees",
        targetEntity = Employer.class
    )
    public Collection getEmployers() {
        return employers;
    }
}                </programlisting>
      </example>

      <para>In this example @JoinTable defines a
      <literal>name, an array of join columns, and an array of
      inverse join columns. The latter ones are the columns of the association
      table which refer to the <classname>Employee primary key
      (the "other side"). As seen previously, the other side don't have to
      (must not) describe the physical mapping: a simple
      <literal>mappedBy argument containing the owner side property
      name bind the two.</para>

      <para>As any other annotations, most values are guessed in a many to
      many relationship. Without describing any physical mapping in a
      unidirectional many to many the following rules applied. The table name
      is the concatenation of the owner table name, <keycap>_ and the
      other side table name. The foreign key name(s) referencing the owner
      table is the concatenation of the owner table name, <keycap>_
      and the owner primary key column(s). The foreign key name(s) referencing
      the other side is the concatenation of the owner property name,
      <keycap>_, and the other side primary key column(s). These are
      the same rules used for a unidirectional one to many
      relationship.</para>

      <example>
        <title>Default values for @ManyToMany
        (uni-directional)</title>

        <programlisting language="JAVA" role="JAVA">@Entity
public class Store {
    @ManyToMany(cascade = CascadeType.PERSIST)
    public Set<City> getImplantedIn() {
        ...
    }
}

@Entity
public class City {
    ... //no bidirectional relationship
}             </programlisting>
      </example>

      <para>A Store_City is used as the join table. The
      <literal>Store_id column is a foreign key to the
      <literal>Store table. The implantedIn_id
      column is a foreign key to the <literal>City table.

      <para>Without describing any physical mapping in a bidirectional many to
      many the following rules applied. The table name is the concatenation of
      the owner table name, <keycap>_ and the other side table name.
      The foreign key name(s) referencing the owner table is the concatenation
      of the other side property name, <keycap>_, and the owner
      primary key column(s). The foreign key name(s) referencing the other
      side is the concatenation of the owner property name,
      <keycap>_, and the other side primary key column(s). These are
      the same rules used for a unidirectional one to many
      relationship.</para>

      <example>
        <title>Default values for @ManyToMany
        (bi-directional)</title>

        <programlisting language="JAVA" role="JAVA">@Entity
public class Store {
    @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    public Set<Customer> getCustomers() {
        ...
    }
}

@Entity
public class Customer {
    @ManyToMany(mappedBy="customers")
    public Set<Store> getStores() {
        ...
    }
}             </programlisting>
      </example>

      <para>A Store_Customer is used as the join table. The
      <literal>stores_id column is a foreign key to the
      <literal>Store table. The customers_id
      column is a foreign key to the <literal>Customer table.

      <para>Using Hibernate mapping files you can map a bidirectional
      many-to-many association by mapping two many-to-many associations to the
      same database table and declaring one end as
      <emphasis>inverse. 
          <para>You cannot select an indexed collection.
        </note>

      <para> shows a
      bidirectional many-to-many association that illustrates how each
      category can have many items and each item can be in many
      categories:</para>

      <example id="example-many-to-many-mapping-file">
        <title>Many to many association using Hibernate mapping files

        <programlisting role="XML"><class name="Category">
    <id name="id" column="CATEGORY_ID"/>
    ...
    <bag name="items" table="CATEGORY_ITEM">
        <key column="CATEGORY_ID"/>
        <many-to-many class="Item" column="ITEM_ID"/>
    </bag>
</class>

<class name="Item">
    <id name="id" column="ITEM_ID"/>
    ...

    <!-- inverse end -->
    <bag name="categories" table="CATEGORY_ITEM" inverse="true">
        <key column="ITEM_ID"/>
        <many-to-many class="Category" column="CATEGORY_ID"/>
    </bag>
</class></programlisting>
      </example>

      <para>Changes made only to the inverse end of the association are
      <emphasis>not persisted. This means that Hibernate has two
      representations in memory for every bidirectional association: one link
      from A to B and another link from B to A. This is easier to understand
      if you think about the Java object model and how a many-to-many
      relationship in Javais created:</para>

      <example>
        <title>Effect of inverse vs. non-inverse side of many to many
        associations</title>

        <programlisting role="JAVA">category.getItems().add(item);           // The category now "knows" about the relationship
item.getCategories().add(category);      // The item now "knows" about the relationship

session.persist(item);                   // The relationship won't be saved!
session.persist(category);               // The relationship will be saved</programlisting>
      </example>

      <para>The non-inverse side is used to save the in-memory representation
      to the database.</para>
    </section>

    <section id="collections-indexedbidirectional">
      <title>Bidirectional associations with indexed collections

      <para>There are some additional considerations for bidirectional
      mappings with indexed collections (where one end is represented as a
      <literal><list> or <map>) when
      using Hibernate mapping files. If there is a property of the child class
      that maps to the index column you can use
      <literal>inverse="true" on the collection mapping:

      <example>
        <title>Bidirectional association with indexed collection

        <programlisting role="XML"><class name="Parent">
    <id name="id" column="parent_id"/>
    ....
    <map name="children" inverse="true">
        <key column="parent_id"/>
        <map-key column="name" 
            type="string"/>
        <one-to-many class="Child"/>
    </map>
</class>

<class name="Child">
    <id name="id" column="child_id"/>
    ....
    <property name="name" 
        not-null="true"/>
    <many-to-one name="parent" 
        class="Parent" 
        column="parent_id"
        not-null="true"/>
</class></programlisting>
      </example>

      <para>If there is no such property on the child class, the association
      cannot be considered truly bidirectional. That is, there is information
      available at one end of the association that is not available at the
      other end. In this case, you cannot map the collection
      <literal>inverse="true". Instead, you could use the following
      mapping:</para>

      <example>
        <title>Bidirectional association with indexed collection, but no index
        column</title>

        <programlisting role="XML"><class name="Parent">
    <id name="id" column="parent_id"/>
    ....
    <map name="children">
        <key column="parent_id"
            not-null="true"/>
        <map-key column="name" 
            type="string"/>
        <one-to-many class="Child"/>
    </map>
</class>

<class name="Child">
    <id name="id" column="child_id"/>
    ....
    <many-to-one name="parent" 
        class="Parent" 
        column="parent_id"
        insert="false"
        update="false"
        not-null="true"/>
</class></programlisting>
      </example>

      <para>Note that in this mapping, the collection-valued end of the
      association is responsible for updates to the foreign key.<!--TODO: Does this really result in some unnecessary update statements?-->
    </section>

    <section id="collections-ternary">
      <title>Ternary associations

      <para>There are three possible approaches to mapping a ternary
      association. One approach is to use a <literal>Map with an
      association as its index:</para>

      <example>
        <title>Ternary association mapping

        <programlisting role="XML">@Entity
public class Company {
   @Id 
   int id;
   ...
   @OneToMany // unidirectional
   @MapKeyJoinColumn(name="employee_id")
   Map<Employee, Contract> contracts;
}

// or

<map name="contracts">
    <key column="employer_id" not-null="true"/>
    <map-key-many-to-many column="employee_id" class="Employee"/>
    <one-to-many class="Contract"/>
</map></programlisting>
      </example>

      <para>A second approach is to remodel the association as an entity
      class. This is the most common approach. A final alternative is to use
      composite elements, which will be discussed later.</para>
    </section>

    <section id="collections-idbag" revision="1">
      <title>Using an <idbag>

      <para>The majority of the many-to-many associations and collections of
      values shown previously all map to tables with composite keys, even
      though it has been suggested that entities should have synthetic
      identifiers (surrogate keys). A pure association table does not seem to
      benefit much from a surrogate key, although a collection of composite
      values <emphasis>might. For this reason Hibernate provides a
      feature that allows you to map many-to-many associations and collections
      of values to a table with a surrogate key.</para>

      <para>The <idbag> element lets you map a
      <literal>List (or Collection) with bag
      semantics. For example:</para>

      <programlisting role="XML"><idbag name="lovers" table="LOVERS">
    <collection-id column="ID" type="long">
        <generator class="sequence"/>
    </collection-id>
    <key column="PERSON1"/>
    <many-to-many column="PERSON2" class="Person" fetch="join"/>
</idbag></programlisting>

      <para>An <idbag> has a synthetic id generator,
      just like an entity class. A different surrogate key is assigned to each
      collection row. Hibernate does not, however, provide any mechanism for
      discovering the surrogate key value of a particular row.</para>

      <para>The update performance of an <idbag>
      supersedes a regular <literal><bag>. Hibernate can
      locate individual rows efficiently and update or delete them
      individually, similar to a list, map or set.</para>

      <para>In the current implementation, the native
      identifier generation strategy is not supported for
      <literal><idbag> collection identifiers.
    </section>
  </section>

  <!--undocumenting this stuff -->

  <!--section id="collections-heterogeneous">
        <title>Heterogeneous Associations

        <para>
            The <literal><many-to-any> and <index-many-to-any>
            elements provide for true heterogeneous associations. These mapping elements work in the
            same way as the <literal><any> element - and should also be used
            rarely, if ever.
        </para>

    </section-->

  <section id="collections-example" revision="1">
    <title>Collection examples

    <para>This section covers collection examples.

    <para>The following class has a collection of Child
    instances:</para>

    <example>
      <title>Example classes Parent and
      <classname>Child

      <programlisting role="JAVA">public class Parent {
    private long id;
    private Set<Child> children;

    // getter/setter
    ...
}


public class Child {
   private long id;
   private String name

   
   // getter/setter
   ...
}</programlisting>
    </example>

    <para>If each child has, at most, one parent, the most natural mapping is
    a one-to-many association:</para>

    <example>
      <title>One to many unidirectional Parent-Child
      relationship using annotations</title>

      <programlisting role="XML">public class Parent {
    @Id
    @GeneratedValue
    private long id;

    @OneToMany
    private Set<Child> children;

    // getter/setter
    ...
}


public class Child {
   @Id
   @GeneratedValue
   private long id;
   private String name;

   
   // getter/setter
   ...
}</programlisting>
    </example>

    <example>
      <title>One to many unidirectional Parent-Child
      relationship using mapping files</title>

      <programlisting role="XML"><hibernate-mapping>

    <class name="Parent">
        <id name="id">
            <generator class="sequence"/>
        </id>
        <set name="children">
            <key column="parent_id"/>
            <one-to-many class="Child"/>
        </set>
    </class>

    <class name="Child">
        <id name="id">
            <generator class="sequence"/>
        </id>
        <property name="name"/>
    </class>

</hibernate-mapping></programlisting>
    </example>

    <para>This maps to the following table definitions:

    <example>
      <title>Table definitions for unidirectional
      <classname>Parent-Child
      relationship</title>

      <programlisting role="XML">create table parent ( id bigint not null primary key )
create table child ( id bigint not null primary key, name varchar(255), parent_id bigint )
alter table child add constraint childfk0 (parent_id) references parent</programlisting>
    </example>

    <para>If the parent is required, use a bidirectional
    one-to-many association:</para>

    <example>
      <title>One to many bidirectional Parent-Child
      relationship using annotations</title>

      <programlisting role="XML">public class Parent {
    @Id
    @GeneratedValue
    private long id;

    @OneToMany(mappedBy="parent")
    private Set<Child> children;

    // getter/setter
    ...
}


public class Child {
   @Id
   @GeneratedValue
   private long id;

   private String name;
 
   @ManyToOne
   private Parent parent;

   
   // getter/setter
   ...
}</programlisting>
    </example>

    <example>
      <title>One to many bidirectional Parent-Child
      relationship using mapping files</title>

      <programlisting role="XML"><hibernate-mapping>

    <class name="Parent">
        <id name="id">
            <generator class="sequence"/>
        </id>
        <set name="children" inverse="true">
            <key column="parent_id"/>
            <one-to-many class="Child"/>
        </set>
    </class>

    <class name="Child">
        <id name="id">
            <generator class="sequence"/>
        </id>
        <property name="name"/>
        <many-to-one name="parent" class="Parent" column="parent_id" not-null="true"/>
    </class>

</hibernate-mapping></programlisting>
    </example>

    <para>Notice the NOT NULL constraint:

    <example>
      <title>Table definitions for bidirectional
      <classname>Parent-Child
      relationship</title>

      <programlisting role="XML">create table parent ( id bigint not null primary key )
create table child ( id bigint not null
                     primary key,
                     name varchar(255),
                     parent_id bigint not null )
alter table child add constraint childfk0 (parent_id) references parent</programlisting>
    </example>

    <para>Alternatively, if this association must be unidirectional you can
    enforce the <literal>NOT NULL constraint.

    <example>
      <title>Enforcing NOT NULL constraint in unidirectional relation using
      annotations</title>

      <programlisting role="XML">public class Parent {
    @Id
    @GeneratedValue
    private long id;

    @OneToMany(optional=false)
    private Set<Child> children;

    // getter/setter
    ...
}


public class Child {
   @Id
   @GeneratedValue
   private long id;
   private String name;

   
   // getter/setter
   ...
}</programlisting>
    </example>

    <example>
      <title>Enforcing NOT NULL constraint in unidirectional relation using
      mapping files</title>

      <programlisting role="XML"><hibernate-mapping>

    <class name="Parent">
        <id name="id">
            <generator class="sequence"/>
        </id>
        <set name="children">
            <key column="parent_id" not-null="true"/>
            <one-to-many class="Child"/>
        </set>
    </class>

    <class name="Child">
        <id name="id">
            <generator class="sequence"/>
        </id>
        <property name="name"/>
    </class>

</hibernate-mapping></programlisting>
    </example>

    <para>On the other hand, if a child has multiple parents, a many-to-many
    association is appropriate.</para>

    <example>
      <title>Many to many Parent-Child relationship
      using annotations</title>

      <programlisting role="XML">public class Parent {
    @Id
    @GeneratedValue
    private long id;

    @ManyToMany
    private Set<Child> children;

    // getter/setter
    ...
}


public class Child {
   @Id
   @GeneratedValue
   private long id;

   private String name;

   
   // getter/setter
   ...
}</programlisting>
    </example>

    <example>
      <title>Many to many Parent-Child relationship
      using mapping files</title>

      <programlisting role="XML"><hibernate-mapping>

    <class name="Parent">
        <id name="id">
            <generator class="sequence"/>
        </id>
        <set name="children" table="childset">
            <key column="parent_id"/>
            <many-to-many class="Child" column="child_id"/>
        </set>
    </class>

    <class name="Child">
        <id name="id">
            <generator class="sequence"/>
        </id>
        <property name="name"/>
    </class>

</hibernate-mapping></programlisting>
    </example>

    <para>Table definitions:

    <example>
      <title>Table definitions for many to many releationship

      <programlisting>create table parent ( id bigint not null primary key )
create table child ( id bigint not null primary key, name varchar(255) )
create table childset ( parent_id bigint not null,
                        child_id bigint not null,
                        primary key ( parent_id, child_id ) )
alter table childset add constraint childsetfk0 (parent_id) references parent
alter table childset add constraint childsetfk1 (child_id) references child</programlisting>
    </example>

    <para>For more examples and a complete explanation of a parent/child
    relationship mapping, see <xref linkend="example-parentchild" /> for more
    information. Even more complex association mappings are covered in the
    next chapter.</para>
  </section>
</chapter>

Other Hibernate examples (source code examples)

Here is a short list of links related to this Hibernate collection_mapping.xml source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.