Hibernate Collection Mapping

Hibernate permits collection mapping as value type. The collection are mapped into a separate table but are not disclosed as entity on the Java side in the hibernate collection mapping and it supports the following interfaces.There are examples listed here on collection mapping.

  1. java.util.Set – java.util.HashSet is used to store value.
  2. java.util.SortedSet – java.util.TreeSet is used to store value.
  3. java.util.List – java.util.ArrayList is used to store value. Preserves the position with an index column
  4. Bag semantics – java.util.ArrayList is used to store value however the position is not preserved.
  5. java.util.Map – java.util.HashMap is used to store value.
  6. java.util.SortedMap – java.util.TreeMap is used to store value.

Hibernate collection can be divided into two different categories. They are

  1. Simple collection mapping
  2. Advanced collection mapping

First we discuss how to handle simple collection mapping and later we will discuss advanced collection mapping. Simple collection mapping can be done in five different ways. They are,

  1. Collection foreign keys
  2. Collection elements
  3. Indexed collection
  4. Collection of values and many to many associations
  5. One to many associations

Advanced collection mapping can be handled through the following ways.

  1. Sorted collections
  2. Bidirectional associations
  3. Bidirectional associations with indexed collections
  4. Ternary associations
  5. Using an <idbag>

Simple collection mapping

1)      Collection foreign keys

Foreign key is used to distinguish collection instances in the database and it referred to as the collection key column, or columns of the collection table. The collection key is mapped by the <key element>. The foreign key constraint also uses ON DELETE CASCADE.

Example 1:- <key column=”productSerialNumber” not-null=”true”/>

Example 2 :- <key column=”productSerialNumber” on-delete=”cascade”/>

2)      Collection elements

Collections can contain any other Hibernate type, including basic types, custom types, components and references to other entities. This is an important distinction. An object in a collection can be handled with the semantics of “value” or it could be a reference to another entity with its own life cycle. In the latter case, only the “relationship” between the two objects is considered to be a state held by the collection.

The content type is referred to as the element type of collection. Collection elements are mapped by <element> or <composite-element>, or in the case of entity references, with or <one-to-many> <many-to-many>. The first two map elements with value semantics, the next two are used to map entity associations.

3)      Indexed collection

Here we are usi9ng index column in the collection table. Index column means it’s a column that maps to an array index, or List index, Map key. Map may be of any basic type mapped with <map-key>. It can be an entity reference mapped with <map-key-many-to-many>, or it can be a composite type mapped with <composite-map-key>.

Example: –

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

1)      column_name (required): the name of the column holding the collection index values. 2)      base (optional – defaults to 0): the value of the index column that corresponds to the first element of the list or array.

<map-key
column="column_name"
formula="any SQL expression"

node="@attribute-name"
length="N"/>

1)      column (optional): the name of the column holding the collection index values. 2)      formula (optional): a SQL formula used to evaluate the key of the map. 3)      type (required): the type of the map keys.

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

1)      column (optional): the name of the foreign key column for the collection index values.

2)      formula (optional): a SQ formula used to evaluate the foreign key of the map key.

3)      class (required): the entity class used as the map key.

4)      Collection of values and many to many associations


Many to many associations require a collection table with foreign key column or columns, collection of elements or columns and index column or columns. A many to many association is specified using the <many-to-many> element. Eg: –

<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"/>

1)      column (optional): the name of the column holding the collection element values. 2)      formula (optional): an SQL formula used to evaluate the element. 3)      type (required): the type of the collection element.

<many-to-many
column="column_name"
formula="any SQL expression"
fetch="select|join"
unique="true|false"
not-found="ignore|exception"
entity-name="EntityName” property-ref="propertyNameFromAssociatedClass"
node="element-name"
embed-xml="true|false” />

5)      One to many associations

A one-to-many link tables of two classes via a foreign key with no intervening collection table. This mapping loses certain semantics of normal Java collections: An instance of the contained entity class may not belong to more than one instance of the instance collection. An of the contained entity class may not appear on more than one value of the association of index. A collection product from Part requires the existence of a foreign key column and possibly an index column to the table of the Party. <one-to-many> Label indicates that an association is one-to-many.

Example: –

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

Advanced Collection Mapping

1)      Sorted collections

Hibernate supports collections implementing and java.util.SortedSet java.util.SortedMap. We should specify a comparator in the mapping file. The allowed values of the attribute type are not rated, natural, and the name of a class that implements java.util.Comparator. Sorted collections actually behave like java.util.TreeSet or java.util.TreeMap.

Example: –

<set name="aliases" table="person_aliases" sort="natural">
<key column="person"/>
<element column="name" type="string"/>
</set>
<map sort="my.custom.HolidayComparator">
<key column="year_id"/>
<map-key column="hol_name"/>
<element column="hol_date"/>
</map>

If you want the database itself to order the collection elements, use the order-by attribute of set, bag or map mappings. This solution is only available under JDK 1.4 or higher and is implemented using LinkedHashSet or LinkedHashMap. This performs the ordering in the SQL query and not in the memory.

<set table="person_aliases" order-by="lower(name) asc">
<key column="person"/>
<element column="name" type="string"/>
</set>
 <map order-by="hol_date, hol_name">
<key column="year_id"/>
<map-key column="hol_name"/>
<element column="hol_date/>
</map>

Associations can even be sorted by arbitrary criteria at runtime using a collection filter()

Example: – sortedUsers = s.createFilter( group.getUsers(), “order by this.name” ).list();

2)      Bidirectional associations

Bidirectional association permits two kinds of association

  • One to many: – Set or bag valued at one end and single valued at the other.
  • Many to many:- Set or bag valued at both ends

3)      Bidirectional associations with indexed collections

A bidirectional association where one end is represented as a <list> or <map>, requires special consideration. If there is a property of the child class that maps to the index column you can use inverse=”true” on the collection mapping

Example: –

<class name="Parent">
<id column="parent_id"/>
....
<map inverse="true">
<key column="parent_id"/>
<map-key column="name"/>
<one-to-many/>
</map>
</class>
<class>
<id column="child_id"/>
....
<property
not-null="true"/>
<many-to-oneparent_id"
not-null="true"/>
</class>

4)      Ternary associations – Ternary association mainly used three approaches.

1)      Use a Map with an association as its index

Eg: –

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

2)      Remodel the association as an entity class

3)      Use composite elements

5)      Using an <idbag>

The <idbag> element helps to map a List (or Collection) with bag semantics.

Example: –

<idbag name="lovers" table="LOVERS">
<collection-id column="ID">
<generator/>
</collection-id>
<key column="PERSON1"/>
<many-to-many column="PERSON2" fetch="join"/> </idbag>