Tuesday, October 18, 2011

One to Many Bidirectional association

In One to many bidirectional association, both sides of the association will have the reference to each other. The one side of the association will implement any one of the collection interfaces to refer the many references.

Mapping using Hibernate XML mapping:

Let us go to the package com.demo.oneToManyBidirectional and execute the class OneToManyBirectionalExecutor.java.

Things to look into:

* The ORM classes User.java and Account.java
* The xml mapping file oneToManyBidirectional.hbm.xml

ORM:

public class User {

private long id;

private String name;

private Set accounts = new HashSet();

// getter and setter methods
}

public class Account {

private long id;

private String accountType;

private User user;

// getter and setter methods
}

* Note that both the entity classes have the reference to each other and hence accomplishes the bidirectional navigation.

XML:

<hibernate-mapping auto-import="false">
<class name="com.demo.oneToManyBidirectional.User" table="USER"
lazy="false">
<id name="id" column="USER_ID">
<generator class="native" />
</id>
<property name="name" column="NAME" />
<set name="accounts" cascade="save-update">
<key column="USER_ID" not-null="true"/>
<one-to-many class="com.demo.oneToManyBidirectional.Account" />
</set>
</class>
<class name="com.demo.oneToManyBidirectional.Account" table="ACCOUNT"
lazy="false">
<id name="id" column="ACCOUNT_ID">
<generator class="native" />
</id>
<property name="accountType" column="ACCOUNT_TYPE" />
<many-to-one name="user" column="USER_ID"
class="com.demo.oneToManyBidirectional.User" not-null="true" insert="false" update="false"/>
</class>
</hibernate-mapping>

* This time the collection values are not stored in a separate table rather they are stored in the target table that is the Account table.
* We are supposed to make any one of the sides of the association as inverse and we intentionally choose to have the many side as inverse. (i.e) we want to store values from the one side and to store the state of the collections.
* As <many-to-one> does not have the inverse attribute, we make use of the insert="false" and update="false" in order to achieve the inverse="true".
* It is also possible to make the one side of the association as inverse and storing the values from the many side.

Once the class OneToManyBirectionalExecutor.java is executed , verify the results in the eclipse console and as well as in the HSQL DB manager by running simple select queries on the tables User and Account as follows.




Mapping using Annotations:

Let us go to the package annotation.com.demo.oneToManyBidirectional and execute the class OneToManyAnnotationBidirectionalExecutor.java

Things to look into:

* The annotated ORM classes User.java and Account.java

@Entity(name="annotation.com.demo.oneToManyBidirectional.User")
@Table(name="USER")
public class User {

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

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

@OneToMany(cascade=CascadeType.ALL,fetch=FetchType.EAGER)
@JoinColumn(name="USER_ID",nullable=false)
private Set accounts = new HashSet();

// getter and setter methods
}


@Entity(name="annotation.com.demo.oneToManyBidirectional.Account")
@Table(name="ACCOUNT")
public class Account {

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

@Column(name="ACCOUNT_TYPE")
private String accountType;

@ManyToOne(fetch=FetchType.EAGER)
@JoinColumn(name="USER_ID",nullable=false,updatable=false,insertable=false)
private User user;

//getter and setter methods
}


*
@OneToMany represents the one-to-many association.
*
@ManyToOne represents the many-to-one association.
*
@JoinColumn refer the foreign key column in the Account table
* updatable=false and insertable=false specify that the many side of the assiciation will participate in the insert or update activities.

Once the OneToManyAnnotationBidirectionalExecutor.java is executed verify the results as mentioned above.