Tuesday, October 18, 2011

Mapping Components

An Entity class can have a reference to another class as a member variable. If the referred class does not have it's own life cycle and completely depends on the life cycle of the owning entity class, then the referred class hence therefore is called as the Component class.

As the component class does not have it's own life cycle, it does not require an id attribute. Hibernate uses the term component for a user-defined class that is persisted to the same table as the owning entity.

Mapping using Hibernate XML mapping:

Let us go to the package com.demo.components and execute the class ComponentExecutor.java

Things to look into:

* The ORM classes
Customers.java and Address.java
* The xml mapping file com.demo.Components.hbm.xml

ORM Classes:

The Customer class is having the references to the Address class. On the other side, the Address class does not have the id attribute as it does not have it's own life cycle.

public class Customers {

private long id;
private String name;
private Address homeAddress;
private Address billingAddress;

//getter and setter methods

}


public class Address {

private String street;
private String zipCode;
private String city;
//getter and setter methods

}


XML mapping file:

<hibernate-mapping auto-import="false">
<class name="com.demo.components.Customers" table="CUSTOMERS">
<id name="id" column="CUSTOMER_ID" type="long">
<generator class="native" />
</id>
<property name="name" column="NAME" type="string" />
<component name="homeAddress" class="com.demo.components.Address">
<property name="street" type="string" column="HOME_STREET"
not-null="true" />
<property name="city" type="string" column="HOME_CITY"
not-null="true" />
<property name="zipCode" type="string" column="HOME_ZIPCODE"
not-null="true" />
</component>
<component name="billingAddress" class="com.demo.components.Address">
<property name="street" type="string" column="BILLING_STREET"
not-null="true" />
<property name="city" type="string" column="BILLING_CITY"
not-null="true" />
<property name="zipCode" type="string" column="BILLING_ZIPCODE"
not-null="true" />
</component>
</class>
</hibernate-mapping>


* The element <component> defines the component part of the entity class and it's class attribute points the component class.
* The component class does not have it's own table.
* All the attributes of the component class are persisted in the table CUSTOMERS which represents the owning entity.
* Here the component class is Address is used to define two different addresses.

Execute the class ComponentExecutor.java and verify the results in the HSQL DB manager by running the following simple select query on the table CUSTOMERS.


Mapping Components using Annotations:

Let us go to the package annotation.com.demo.components and execute the class ComponentAnnotationExecutor.java

Things to look into:

* The annotated ORMs Customers.java and Address.java

The Address.java has been marked with an annotation @Embeddable which will indicate that the objects of this class can be referred from other entity classes. Note that Address class does not have the id attribute which indicates that it is a component class.

@Embeddable
public class Address {

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

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

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

// getter and setter methods
}

The Customer.java which is a entity class is given below.

@Entity
@Table(name="CUSTOMERS")
public class Customers {

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

@Column(name="NAME")
private String name;

@Embedded
@AttributeOverrides({
@AttributeOverride(name="street", column = @Column(name="HOME_STREET")),
@AttributeOverride(name="zipCode", column = @Column(name="HOME_ZIPCODE")),
@AttributeOverride(name="city", column=@Column(name="HOME_CITY"))
})
private Address homeAddress;

@Embedded
@AttributeOverrides({
@AttributeOverride(name="street", column = @Column(name="BILLING_STREET")),
@AttributeOverride(name="zipCode", column = @Column(name="BILLING_ZIPCODE")),
@AttributeOverride(name="city", column=@Column(name="BILLING_CITY"))
})
private Address billingAddress;


*
@Embedded annotation specifies that this class embeds a reference to an another class.
*
@AttributeOverrides contains a set of @AttributeOverride annotations.
*
@AttributeOverrides annotation maps the attributes of the component class to the
columns of the table
which represents the owning entity class.

After executing the class ComponentAnnotationExecutor.java verify the results as mentioned above.