Tuesday, October 18, 2011

Mapping Collection of Components

The mapping of Collection of Components is done in a similar way just as the mapping of regular Collections. The only difference is that we use the xml element <composite-element> instead of the <element> tag.

Mapping using Hibernate XML mapping:

Let us go to the package com.demo.collectionOfComponents and execute the class CollectionComponentExecutor.java

Things to look into:

* The ORM classes Candidate.java and Recruitment.java
* The xml mapping file com.demo.collectionOfComponents.hbm.xml

ORM:

The Candidate.java is the component class and it does not have it's own life cycle. It is completely dependent on the owing entity class Recruitment.java. Note that the Candidate class has a reference back to the Recruitment class. We will explain this in the xml mapping.

public class Candidate {

private String name;

private int age;

private String qualification;

private String experience;

private Recruitment recruitment;

// getter and setter methods

}

public class Recruitment {

private long id;

private String recruitmentName;

private Set selectedCandidates = new HashSet();

private Set rejectedCandidates = new HashSet();

// getter and setter methods

}

XML mapping:

<hibernate-mapping auto-import="false">
<class name="com.demo.collectionOfComponents.Recruitment" table="RECRUITMENTS" lazy="false">
<id name="id" column="RCRMT_ID">
<generator class="native" />
</id>
<property name="recruitmentName" column="RCRMT_NAME" />

<set name="selectedCandidates" table="SELECTED_LIST" order-by="name asc"
lazy="false">
<key column="RCRMT_ID" />
<composite-element class="com.demo.collectionOfComponents.Candidate">
<parent name="recruitment" />
<property name="name" column="NAME"/>
<property name="age" column="AGE"/>
<property name="qualification" column="QUALIFICATION"/>
<property name="experience" column="EXPERIECE"/>
</composite-element>
</set>

<set name="rejectedCandidates" table="REJECTED_LIST" order-by="name asc"
lazy="false">
<key column="RCRMT_ID" />
<composite-element class="com.demo.collectionOfComponents.Candidate">
<parent name="recruitment" />
<property name="name" column="NAME"/>
<property name="age" column="AGE"/>
<property name="qualification" column="QUALIFICATION"/>
<property name="experience" column="EXPERIECE"/>
</composite-element>
</set>
</class>
</hibernate-mapping>

* <set> specifies that that attribute selectedCandidates and rejectedCandidates are of type
set collection.

* <key> declares the foreign key column of the collection table.

* <composite-element> represents the collection of component class objects.

* <parent> is a reference from the component class to the owning entity. This is useful only in rare cases, because a componet class can not exist on it's own and it will exist only when entity class exists.

Execute the class CollectionComponentExecutor.java and run the simple select queries on the tables RECRUITMENTS, SELECTED_LIST, REJECTED_LIST as follows.




Mapping using Annotations:

Let us go to the package annotation.com.demo.collectionOfComponents and execute the class CollectionOfComponentsAnnotationExecutor.java

Things to look into:

* The annotated ORM classes Candidate.java and Recruitment.java

@Embeddable
public class Candidate {

@Column(name="NAME",nullable=false)
private String name;

@Column(name="AGE",nullable=false)
private int age;

@Column(name="qualification",nullable=false)
private String qualification;

@Column(name="experience",nullable=false)
private String experience;

@org.hibernate.annotations.Parent
private Recruitment recruitment;

// getter and setter methods
}

@Entity
@Table(name="RECRUITMENTS")
public class Recruitment {

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

@Column(name="RCRMT_NAME")
private String recruitmentName;

@org.hibernate.annotations.CollectionOfElements
@JoinTable(name="SELECTED_LIST",joinColumns=@JoinColumn(name="RCRMT_ID"))
@AttributeOverrides({
@AttributeOverride(name="name", column = @Column(name="NAME")),
@AttributeOverride(name="age", column = @Column(name="AGE")),
@AttributeOverride(name="qualification", column=@Column(name="QUALIFICATION")),
@AttributeOverride(name="experience", column=@Column(name="EXPERIECE"))
})
private Set selectedCandidates = new HashSet();

@org.hibernate.annotations.CollectionOfElements
@JoinTable(name="REJECTED_LIST",joinColumns=@JoinColumn(name="RCRMT_ID"))
@AttributeOverrides({
@AttributeOverride(name="name", column = @Column(name="NAME")),
@AttributeOverride(name="age", column = @Column(name="AGE")),
@AttributeOverride(name="qualification", column=@Column(name="QUALIFICATION")),
@AttributeOverride(name="experience", column=@Column(name="EXPERIECE"))
})
private Set rejectedCandidates = new HashSet();

// getter and setter methods
}

Candidate.java:

* The annotation
@Embeddable specifies that the reference to the objects of this class can be embedded in other classes.

* The hibernate annotation @org.hibernate.annotations.Parent specifies the owning entity class.

Recruitment.java:

* The hibernate annotation @org.hibernate.annotations.CollectionOfElements specifies that the variable is of the type Collections.

* @JoinTable specifies the Collection table that will store the collection values.

* @AttributeOverrides contains a set of @AttributeOverride annotations.

* @AttributeOverride maps the attributes of the component class to the columns in the collection table

Once the class CollectionOfComponentsAnnotationExecutor.java is executed verify the results as described above.