Tuesday, October 18, 2011

Mapping Collections in Hibernate using Bag semantics

An unordered collection that permits a duplicate elements is called a bag. Java Collections framework does not provide a bag implementation. However, hibernate has a built-in Persistent Bag that can deal with lists. All we have to do in our java class is implementing the java.util.Collection interface or java.util.List interface using the java.util.ArrayList. Hibernate will do the rest of the bag semantics.

When you are not considering the order and the duplicate elements, it is advisable to use this bag implementation which will improve the performance of hibernate a lot.

Mapping using Hibernate XML mapping:

Let us go the package com.demo.collections.Bag and execute the BagExecutor.java.

Things to look into:

* The ORM class Tour.java
* The xml mapping file com.demo.collections.Bag.hbm.xml

ORM:

The variable travelledCountries has been declared using the java.util.Collection interface.

public class Tour {

private long id;

private String touristName;

private int numberOfTimesTravelled;

private Collection travelledCountries = new ArrayList();

// getter and setter methods

}

XML mapping file:

<hibernate-mapping auto-import="false">
<class name="com.demo.collections.Bag.Tour" table="TOURS" lazy="false">
<id name="id" column="TOURIST_ID" type="long">
<generator class="native" />
</id>
<property name="touristName" column="TOURIST_NAME"></property>
<property name="numberOfTimesTravelled" column="NUMBER_OF_TRAVELS"
type="integer" />
<!-- Declaration for Bag -->
<idbag name="travelledCountries" table="COUNTRIES" lazy="false">
<collection-id type="string" column="BAG_TABLE_ID">
<generator class="sequence"/>
</collection-id>
<key column="TOURIST_ID" />
<element type="string" column="COUNTRY" not-null="true" />
</idbag>
</class>
</hibernate-mapping>

* The xml element <idbag> will take care of the bag semantics in hibernate.
* The element <collection-id> defines the primay key of the collections table.
* The native generator of the primary key is not supproted for mappings and hence we use the sequence primary key generator.
* The key specifies that the primary key of the table TOURS will be the foreign key in the table COUNTRIES.
* The xml element element represents the column in the collections table to store the collection values.

After executing BagExecutor.java, run the simple select queries on the tables TOURS and COUNTRIES and verify the outputs in the eclipse console and in the HSQL DB manager as follows.



Mapping Bag using Annotations:

Let us go to the package annotation.com.demo.collections.Bag and execute the class BagAnnotationExecutor.java

Things to look into:

* The annotated ORM Tour.java

@Entity
@Table(name="TOURS")
public class Tour {

@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="TOURIST_ID")
private long id;

@Column(name="TOURIST_NAME")
private String touristName;

@Column(name="NUMBER_OF_TRAVELS")
private int numberOfTimesTravelled;


@CollectionOfElements(targetElement=java.lang.String.class, fetch=FetchType.EAGER)
@JoinTable(name="COUNTRIES",joinColumns=@JoinColumn(name="TOURIST_ID"))
@org.hibernate.annotations.CollectionId(columns=@Column(name="BAG_TABLE_ID"),
type=@org.hibernate.annotations.Type(type="string"),
generator="sequence")
@Column(name="COUNTRY")
private Collection travelledCountries = new ArrayList();

* The hibernate annotation @org.hibernate.annotations.CollectionOfElements indicates that the variable travelledCountries is of the type collections.
* The targetElement represents the type of element that collection stores and not required if we use the java Generics.
* The annotation @JoinTable is used to mention the table that is used to store the collection values.
* The annotation @JoinColumn here is equivalent to the xml element as mentioned above.
* The hibernate annotation @org.hibernate.annotations.CollectionId specifies the priamy key column of the collections table.

After executing the BagAnnotationExecutor.java, verify the results in the console and in the HSQL DB manager as mentioned above.