Please be informed that NONE of the design/code from this
page is claiming to be some sort of best practices and we DO NOT expect
any of our visitor/reader of this page to assume this as some sort of
best practice for any context and should not be using this
as it is without appropriate evaluation to their, so to say,
specific programming context.
This page intends only to provide bit and piece of known ways for
doing some sort of example and may not be fit for any other purpose.
Hibernate mapping explained:
Many-to-Many type of mapping
example:
Case study: A person can play many
Roles, and a Role can be played
by many Persons.
This case study is not something entirely new concept, but at least
a very simple and straight forward pne, so I have choosen this case
study to understand Many to Many relationship between two different
POJO class files.
|
|
So Persons and Roles can share a many-to-many type of mapping.
My Software environment for this example:
1. Eclipse 3.2
2. JDK 1.5
3. Hibernate 3.2
Hibernate many to many mapping can be realized by using specific tags
like <many-to-many>, but I am using it along with <set> tag (of course
one can use <bag>, <array>, <map>, <list> etc as well, with a different
approach).
In this example, POJO (Plain Old Java Object) are Person and Role.
/**
* This source is provided as is, without any warranty
* and /or guaranty of any kind.
* Copyright (C) 2008, ISHTIAK, All Rights Reserved.
* You can use it for Personal Learning purpose only.
* E-mail: usingframeworks@gmail.com
*/
Person.java
package demo;
import java.util.Set;
public class Person {
private int personId;
private String personName;
private Set roles;
public Person() {
}
public void setPersonId(int personId) {
this.personId = personId;
}
public int getPersonId() {
return this.personId;
}
public void setPersonName(String personName) {
this.personName = personName;
}
public String getPersonName() {
return this.personName;
}
public void setRoles(Set roles) {
this.roles = roles;
}
public Set getRoles() {
return this.roles;
}
}
Person has a many to many relationship with Role, as a Person
can have many Roles and a Role can be assigned to many Persons.
/**
* This source is provided as is, without any warranty
* and /or guaranty of any kind.
* Copyright (C) 2008, iSHTIAK, All Rights Reserved.
* You can use it for Personal Learning purpose only.
* E-mail: usingframeworks@gmail.com
*/
Role.java
package demo;
import java.util.Set;
public class Role {
private int roleId;
private String roleName;
private Set persons;
public Role() {
}
public void setRoleId(int roleId) {
this.roleId = roleId;
}
public int getRoleId() {
return this.roleId;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
public String getRoleName() {
return this.roleName;
}
public void setPersons(Set persons) {
this.persons = persons;
}
public Set getPersons() {
return this.persons;
}
}
HBM mapping file is as mentioned below:
In order to create this mapping, first of all I place normal <class>
tag for Person and Role, with a id for the primary key and property tags
for each fields within Person and Role.
In order to align a many to many mapping, there could be two one-to-many
mapping from either sides, like a one to many mapping from person to role
and a one to many mapping from role to person. Thus eventually making a
many to many mapping of person with role and vice versa.
But in this way of mapping, if the foreign key column is declared to be
not null, then there is no way one can insert a record in either in person
table or in role table, and this type of many to many mapping won't work.
In this example I have used many-to-many tag for doing many to many type
of Hibernate mapping. In this way of many to many mapping, I had to create
a separate table "persons_roles" for holding corresponding foreign keys to
the two primary keys, one from person table and the other from role table.
In order to use <many-to-many> tag , one should have a collection
of many items at both sides, and we can see roles field in person and
persons field in role are defined as java.util.Set.
So there has to have a collection tag like <set> tag inside <class>
tag for person and role.
<set> tag has a <key> tag and a <many-to-many> tag.
For person it can be read as "a set of roles
defined in persons_roles table, with key as role_id_r column in
persons_roles table and mapped as many to many of type
Role and column it refers in persons_roles as role_id_r".
This is from person side, then from role side, <set> can be
read as "a set of persons
defined in persons_roles table, with key as person_id_r column in
persons_roles table and mapped as many to many of type Person and
column it refers in persons_roles as person_id_r".
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="demo">
<class name="Person" table="person">
<id name="personId" column="person_id">
<generator class="assigned"/>
</id>
<property name="personName" column="person_name" type="java.lang.String"/>
<set name="roles" table="persons_roles">
<key column="person_id_r" />
<many-to-many column="role_id_r" class="Role"/>
</set>
</class>
<class name="Role" table="role">
<id name="roleId" column="role_id">
<generator class="assigned"/>
</id>
<property name="roleName" column="role_name" type="java.lang.String"/>
<set name="persons" table="persons_roles">
<key column="role_id_r"/>
<many-to-many column="person_id_r" class="Person" />
</set>
</class>
</hibernate-mapping>
Corresponding tables in database (for this example, I have used HSQLDB), following
are the SQL (for HSQLDB as database):
create table person
(person_id integer not null, person_name varchar(50), primary key (person_id));
create table role
(role_id integer not null, role_name varchar(50), primary key (role_id));
create table persons_roles
(person_id_r integer, role_id_r integer, foreign key(role_id_r)
references role(role_id)), foreign key(person_id_r) references person(person_id));
hibernate.cfg.xml file that contains all the configuration settings for this
example is as shown below:
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- properties -->
<property name="connection.driver_class">org.hsqldb.jdbcDriver</property>
<property name="connection.url">jdbc:hsqldb:hsql://localhost/</property>
<property name="connection.username">sa</property>
<property name="connection.password"></property>
<property name="dialect">org.hibernate.dialect.HSQLDialect</property>
<property name="show_sql">true</property>
<property name="current_session_context_class">thread</property>
<!-- mapping files -->
<mapping resource="demo/PersonRole.hbm.xml"/>
</session-factory>
</hibernate-configuration>
Client code for testing this example could be something like as follows:
if(sessionFactory != null) {
Session session = sessionFactory.getCurrentSession();
Transaction trans = session.getTransaction();
trans.begin();
Role role1 = new Role();
role1.setRoleId(1000);
role1.setRoleName("test role1");
Role role2 = new Role();
role2.setRoleId(1001);
role2.setRoleName("test role2");
session.persist(role1);
session.persist(role2);
Set set = new HashSet();
set.add(role1);
set.add(role2);
Person person = new Person();
person.setPersonId(1000);
person.setPersonName("test");
person.setRoles(set);
session.persist(person);
trans.commit();
}
Here in this client, I am just creating two Roles (role1 and role2) and then
creating a person and associating these already created roles to person.
This way, I am getting a following console as output:
Hibernate: insert into role (role_name, role_id) values (?, ?)
Hibernate: insert into role (role_name, role_id) values (?, ?)
Hibernate: insert into person (person_name, person_id) values (?, ?)
Hibernate: insert into persons_roles (person_id_r, role_id_r) values (?, ?)
Hibernate: insert into persons_roles (person_id_r, role_id_r) values (?, ?)
This means I have managed to create a many to many mapping persisted in
database tables.
 | Author of this article/writeup has expressed his/her willingness |
to help or guide users with any technical difficulties he/she faces
while working with the example code environment setting up, running
and resolving any such exception raised during compile or at runtime.
You may ask for any technical doubt or seek technical help related to
this article by using following form to reach for technical help
from the Author for FREE.
This article's Author shall be reading your request and responding
within reasonable time (no resolution timeframe defined as such).
|
|