Monday, November 20, 2006

Mapping Hibernate many to many associations

Let me walk you through creating sample M N association with hibernate. M N associations require 2 entities table and one link table to map the association. The example I took is for groups and users. A group can have many users and one user can belong to many groups. Think of your workplace. User Rajeev Jha is part of HR group, La montage group and Serve Chilled Beer group. At the same time La Montage group has many other members including coolcat, fred and Wilma. The problem is to map this association using hibernate.

create table contact (

contact_id int(11) not null auto_increment ,
last_name varchar(50),
first_name varchar(50),
primary key (contact_id)) engine=innodb ;

create table my_user (
user_id int(11) not null auto_increment ,
last_name varchar(50),
first_name varchar(50),
primary key (user_id)) engine=innodb ;

create table my_group (
group_id int(11) not null auto_increment ,
name varchar(50),
primary key (group_id)) engine=innodb ;

create table user_group(
user_group_id int(11) not null auto_increment ,
group_id int(11) not null ,
user_id int(11) not null ,
primary key (user_group_id)) engine=innodb ;

user group is the link table. Now we want to see the mapping files for user and group classes. There is no need for a separate mapping file in case of mysql if you are using the auto_increment primary keys. But when I map to oracle , i usually keep a mapping file for link table also. Just map the link table primary key column. The mappings for groups follow in User.hbm.xml. This is the inverse end of relationship. I have omitted other property mappings for brevity sake.

<set name="groups" table="user_group" inverse="true" lazy="true" cascade="save-update">
<key column="user_id"/>
<many-to-many class="com.agiti.hib.Group" column="group_id" />
</set>

And this is the mapping for Group table, that contains users , the inverse end of the relationship inside Group.hbm.xml . I just followed along the hibernate bible . idbag is require to generate the PK for the link table.

<idbag name="users" table="user_group" lazy="true" cascade="save-update" >
<collection-id column="user_group_ID" type="java.lang.Long">
<generator class="increment"/>
</collection-id>
<key column="group_id"/>
<many-to-many column="user_id" class="com.agiti.hib.User"/>

After you are through with the mappings, create or reverse engineer the POJO classes. inside Group.java, the relevant bits are :

public class Group{

private Long id ;
private String name ;
private List users = new ArrayList();

public List getUsers(){ return this.users ;}
public void setUsers(List users){ this.users = users ;}
// other details nuked
public void addUser(User user){
this.users.add(user);
user.getGroups().add(this);
}

}

You can write User.java on the same lines. After that it is just a matter of using your POJO classes.

© Life of a third world developer
Maira Gall