Welcome to the Hibernate Tutorial Series. In previous tutorial we saw how to implement One-to-one Annotation mapping as well as XML mapping. In this tutorial we will understand How to implement Bi-directional One-to-Many relationship in Hibernate using XML mappings.
First let us see the formal definition of One-to-Many relationship:
One-To-Many Relationship: A relationship in which each record in one table is linked to multiple records in another table.
Let us see how to implement One-to-Many relationship in Hibernate using XML mapping.
1. Create Database
For this example, we will MySQL database. Create following two tables in MySQL. Note that Employee and Department table exhibits One-to-many relationship. Each Department can be associated with multiple Employees and each Employee can have only one Department.
CREATE TABLE `department` (
`department_id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`dept_name` VARCHAR(50) NOT NULL DEFAULT '0',
PRIMARY KEY (`department_id`)
)
COLLATE='latin1_swedish_ci'
ENGINE=InnoDB
ROW_FORMAT=DEFAULT
AUTO_INCREMENT=115
CREATE TABLE `employee` (
`employee_id` BIGINT(10) NOT NULL AUTO_INCREMENT,
`firstname` VARCHAR(50) NULL DEFAULT NULL,
`lastname` VARCHAR(50) NULL DEFAULT NULL,
`birth_date` DATE NULL DEFAULT NULL,
`cell_phone` VARCHAR(15) NULL DEFAULT NULL,
`department_id` BIGINT(20) NULL DEFAULT NULL,
PRIMARY KEY (`employee_id`),
INDEX `FK_DEPT` (`department_id`),
CONSTRAINT `FK_DEPT` FOREIGN KEY (`department_id`) REFERENCES `department` (`department_id`)
)
COLLATE='latin1_swedish_ci'
ENGINE=InnoDB
ROW_FORMAT=DEFAULT
Code language: SQL (Structured Query Language) (sql)
2. Hibernate Maven Dependency
We are using Maven for dependency management. Copy following in the pom.xml.
File: pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>net.viralpatel.hibernate</groupId>
<artifactId>HibernateHelloWorldXML</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>HibernateHelloWorldXML</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.10</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate</artifactId>
<version>3.2.6.ga</version>
</dependency>
</dependencies>
</project>
Code language: HTML, XML (xml)
3. Hibernate Model Class
Employee and Department model classes are created which maps to the corresponding database tables.
File: Department.java
package net.viralpatel.hibernate;
import java.util.Set;
public class Department {
private Long departmentId;
private String departmentName;
private Set<Employee> employees;
// Getter and Setter methods
}
Code language: Java (java)
File: Employee.java
package net.viralpatel.hibernate;
import java.sql.Date;
public class Employee {
private Long employeeId;
private String firstname;
private String lastname;
private Date birthDate;
private String cellphone;
private Department department;
public Employee() {
}
public Employee(String firstname, String lastname, Date birthdate,
String phone) {
this.firstname = firstname;
this.lastname = lastname;
this.birthDate = birthdate;
this.cellphone = phone;
}
// Getter and Setter methods
}
Code language: Java (java)
4. Hibernate Utility Class
To access Hibernate API, we will create a wrapper utility class which provides us with SessionFactory.
File: HibernateUtil.java
package net.viralpatel.hibernate;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateUtil {
private static final SessionFactory sessionFactory = buildSessionFactory();
private static SessionFactory buildSessionFactory() {
try {
// Create the SessionFactory from hibernate.cfg.xml
return new Configuration().configure().buildSessionFactory();
} catch (Throwable ex) {
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
}
Code language: Java (java)
5. Hibernate Mapping XML (hbm)
Following are the hibernate mapping files for each enitity Employee and Department.
File: Employee.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="net.viralpatel.hibernate">
<class name="Employee" table="EMPLOYEE">
<id name="employeeId" column="EMPLOYEE_ID">
<generator class="native" />
</id>
<property name="firstname" />
<property name="lastname" column="lastname" />
<property name="birthDate" type="date" column="birth_date" />
<property name="cellphone" column="cell_phone" />
<many-to-one name="department" class="net.viralpatel.hibernate.Department" fetch="select">
<column name="department_id" not-null="true" />
</many-to-one>
</class>
</hibernate-mapping>
Code language: HTML, XML (xml)
File: Department.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="net.viralpatel.hibernate">
<class name="Department" table="DEPARTMENT">
<id name="departmentId" type="java.lang.Long" column="DEPARTMENT_ID" >
<generator class="native" />
</id>
<property name="departmentName" column="DEPT_NAME"/>
<set name="employees" table="employee"
inverse="true" lazy="true" fetch="select">
<key>
<column name="department_id" not-null="true" />
</key>
<one-to-many class="net.viralpatel.hibernate.Employee" />
</set>
</class>
</hibernate-mapping>
Code language: HTML, XML (xml)
6. Review Project Structure
Note that we have used SET to map employees with department. A <set> is similar to except that it can only store unique objects. That means no duplicate elements can be contained in a set. When you add the same element to a set for second time, it will replace the old one. A set is unordered by default but we can ask it to be sorted. The corresponding type of a <set> in Java is java.util.Set
.
Execute <set> example
File: Main.java
package net.viralpatel.hibernate;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
public class Main {
public static void main(String[] args) {
SessionFactory sf = HibernateUtil.getSessionFactory();
Session session = sf.openSession();
session.beginTransaction();
Department department = new Department();
department.setDepartmentName("Sales");
session.save(department);
Employee emp1 = new Employee("Nina", "Mayers", "1212");
Employee emp2 = new Employee("Tony", "Almeida", "4343");
emp1.setDepartment(department);
emp2.setDepartment(department);
session.save(emp1);
session.save(emp2);
session.getTransaction().commit();
session.close();
}
}
Code language: Java (java)
Output:
Hibernate: insert into DEPARTMENT (DEPT_NAME) values (?)
Hibernate: insert into EMPLOYEE (firstname, lastname, birth_date, cell_phone, department_id) values (?, ?, ?, ?, ?)
Hibernate: insert into EMPLOYEE (firstname, lastname, birth_date, cell_phone, department_id) values (?, ?, ?, ?, ?)
Code language: SQL (Structured Query Language) (sql)
7. One-to-Many <bag> example
A <bag> is an unordered collection, which can contain duplicated elements. That means if you persist a bag with some order of elements, you cannot expect the same order retains when the collection is retrieved. There is not a “bag” concept in Java collections framework, so we just use a java.util.List
correspond to a <bag>.
To implement Bag in our one-to-many mapping example, we will do following changes:
7.1 Update Department Model Class
File: Department.java
package net.viralpatel.hibernate;
import java.util.ArrayList;
import java.util.List;
public class Department {
private Long departmentId;
private String departmentName;
private List<Employee> employees;
// Getter and Setter methods
}
Code language: Java (java)
7.2 Update XML Mapping
File: Department.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="net.viralpatel.hibernate">
<class name="Department" table="DEPARTMENT">
<id name="departmentId" type="java.lang.Long" column="DEPARTMENT_ID" >
<generator class="native" />
</id>
<property name="departmentName" column="DEPT_NAME"/>
<bag name="employees" table="employee"
inverse="true" lazy="true" fetch="select">
<key>
<column name="employee_id" not-null="true" />
</key>
<one-to-many class="net.viralpatel.hibernate.Employee" />
</bag>
</class>
</hibernate-mapping>
Code language: HTML, XML (xml)
7.3 Execute <bag> example
Execute the same Main.java file that we created in above example.
Output:
Hibernate: insert into DEPARTMENT (DEPT_NAME) values (?)
Hibernate: insert into EMPLOYEE (firstname, lastname, birth_date, cell_phone, department_id) values (?, ?, ?, ?, ?)
Hibernate: insert into EMPLOYEE (firstname, lastname, birth_date, cell_phone, department_id) values (?, ?, ?, ?, ?)
Code language: SQL (Structured Query Language) (sql)
8. One-to-Many <list> example
A <list> is an indexed collection where the index will also be persisted. That means we can retain the order of the list when it is retrieved. It differs from <bag> for it persists the element Index while a <bag> does not. The corresponding type of a <list> in Java is java.util.List.
To implement List in our one-to-many mapping example, we will do following changes:
8.1 Add Index Column in Employee Table
DROP TABLE if exists `employee`;
CREATE TABLE `employee` (
`employee_id` BIGINT(10) NOT NULL AUTO_INCREMENT,
`firstname` VARCHAR(50) NULL DEFAULT NULL,
`lastname` VARCHAR(50) NULL DEFAULT NULL,
`birth_date` DATE NULL DEFAULT NULL,
`cell_phone` VARCHAR(15) NULL DEFAULT NULL,
`department_id` BIGINT(20) NULL DEFAULT NULL,
`idx` INT(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`employee_id`),
INDEX `FK_DEPT` (`department_id`),
CONSTRAINT `FK_DEPT` FOREIGN KEY (`department_id`) REFERENCES `department` (`department_id`)
)
COLLATE='latin1_swedish_ci'
ENGINE=InnoDB
ROW_FORMAT=DEFAULT
Code language: SQL (Structured Query Language) (sql)
Note that in our existing Employee table we added a new column ‘idx’ which stores the index value for each record.
8.2 Update Model Object
File: Department.java
package net.viralpatel.hibernate;
import java.util.List;
public class Department {
private Long departmentId;
private String departmentName;
private List<Employee> employees;
// Getter and Setter methods
}
Code language: Java (java)
8.3 Update XML Mapping
File: Department.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="net.viralpatel.hibernate">
<class name="Department" table="DEPARTMENT">
<id name="departmentId" type="java.lang.Long" column="DEPARTMENT_ID">
<generator class="native" />
</id>
<property name="departmentName" column="DEPT_NAME"/>
<list name="employees" table="employee"
inverse="false" cascade="all">
<key column="department_id" />
<list-index column="idx" />
<one-to-many class="net.viralpatel.hibernate.Employee" />
</list>
</class>
</hibernate-mapping>
Code language: HTML, XML (xml)
In the above hibernate mapping xml file, note that we have added list tag to map a list of employees with department. Also a new index column “idx” is defined which will store the index of records. Note that inverse=”false” is specified in the mapping which makes Department as the relationship owner. Thus when department object is saved, it automatically saves the Employees too. This is required so that Department can manage the index values for employees. The department_id is given as key column.
8.4 Execute <list> example
Output:
Hibernate: insert into DEPARTMENT (DEPT_NAME) values (?)
Hibernate: insert into EMPLOYEE (firstname, lastname, birth_date, cell_phone) values (?, ?, ?, ?)
Hibernate: insert into EMPLOYEE (firstname, lastname, birth_date, cell_phone) values (?, ?, ?, ?)
Hibernate: update EMPLOYEE set department_id=?, idx=? where EMPLOYEE_ID=?
Hibernate: update EMPLOYEE set department_id=?, idx=? where EMPLOYEE_ID=?
Code language: SQL (Structured Query Language) (sql)
9. One-to-Many <array> example
An <array> has the same usage as a <list> except that it corresponds to an Array type in Java and not a java.util.List. It is rarely used unless we are mapping for legacy applications. In most cases, we should use <list> instead. That is because the size of an array cannot be increased or decreased dynamically, where as a list can.
To implement Array in our one-to-many mapping example, we will do following changes:
9.1 Update Model Object
File: Department.java
package net.viralpatel.hibernate;
public class Department {
private Long departmentId;
private String departmentName;
private Employee[] employees;
// Getter and Setter methods
}
Code language: Java (java)
We simply change the List
of Employees to Array of Employee []
.
9.2 Update XML Mapping
File: Department.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="net.viralpatel.hibernate">
<class name="Department" table="DEPARTMENT">
<id name="departmentId" type="java.lang.Long" column="DEPARTMENT_ID">
<generator class="native" />
</id>
<property name="departmentName" column="DEPT_NAME"/>
<array name="employees" table="employee"
inverse="false" cascade="all">
<key column="department_id" />
<list-index column="idx" />
<one-to-many class="net.viralpatel.hibernate.Employee" />
</array>
</class>
</hibernate-mapping>
Code language: HTML, XML (xml)
9.2 Execute <array> example
Execute the same Main.java class that we created in above <list>
example.
Output:
Hibernate: insert into DEPARTMENT (DEPT_NAME) values (?)
Hibernate: insert into EMPLOYEE (firstname, lastname, birth_date, cell_phone) values (?, ?, ?, ?)
Hibernate: insert into EMPLOYEE (firstname, lastname, birth_date, cell_phone) values (?, ?, ?, ?)
Hibernate: update EMPLOYEE set department_id=?, idx=? where EMPLOYEE_ID=?
Hibernate: update EMPLOYEE set department_id=?, idx=? where EMPLOYEE_ID=?
Code language: SQL (Structured Query Language) (sql)
Download Source Code
Hibernate-one-to-many-set-xml.zip (9 kb)
Hibernate-one-to-many-bag-xml.zip (9 kb)
Hibernate-one-to-many-list-xml.zip (9 kb)
Hibernate-one-to-many-array-xml.zip (9 kb)
i want one to many map example. where no cascade option is used.
Ah, so THAT’s how you do Lists in Hibernate! The index is (in retrospect, obviously) important. Thank you very much for this information.
I am confused about the Key Columns in your source code.
confusing can anybody explain it plz
Excellent article. Do you have an example how to list the employees of one department?
Really helpful example
Just I have a small doubt, like why do we need to mention many-to-one relationship
does it make any circular reference problem?
A points B, B points A
Exception in thread “main” org.hibernate.PropertyValueException: not-null property references a null or transient value: hib.Employee.department
Thanks ,Helpful tutorial but having doubt why is there circular reference In both the hbm files.?
How do we delete the child records linked with particular parent. Any help would be appreciated.
Hi All,
I am getting following error while saving a list of department first and then employee in the same transaction. kindly help me out
this issue is business services and data service create your application some time are missing parameter name or value that time occuer this error
Really very good conceptual example .Everyone able to understand easily.
Hi i am a beginner and i don’t understand why here you are using pom xml.., please kindly revert me back.
Thank you!!!
Excellent article !!!!
@ Nirmal “Hi i am a beginner and i don’t understand why here you are using pom xml.., please kindly revert me back.”
-> Nirmal If you read these in above article it would be clear why is he using pom.xml
2. Hibernate Maven Dependency
We are using Maven for dependency management. Copy following in the pom.xml.
Hence, pom.xml file is used for dependency management. It has nothing to do with if your java project uses hibernate or not.
Thanks good explaination..If anybody wants to know the Interview questions with answers then please go through this blog http://adnjavainterview.blogspot.in/
Hi,
Iam struck in creating a one to many relation and related hb’s and java objects.
Probelm: Iam creating that a Lecturer who is belonging to multiple departments .
i.e Lecturer table should have entries like
L1 D1
L1 D2
L1 D3
L2 D1
L2 D3..
and so on…..
Can you plz. give me solution for this how you create DB tables, hbm files and also java objects.
Thanks.
Hi Viral,
I am a senior java developer yet for hibernate I always use your blogs for reference. Great job.