Hibernate One to Many Relationship Example(Annotation Based)

By Dhiraj Ray, 01 March,2017   711

In this article we will be discussing about one to many relaionship in hibernate with annotations based configuration. We will be creating a simple employee - department one to many relationship and discuss the different annotations used in the example. We will be also discussing about unidirectional and bidirectional relationship seperately and define the configurations for each relationships along with the different optional parameters used in one to many relationship.

What is One to Many Relationship

A one to many entity relationship shows the association of an instance of an entity with multiple instances of another entity. Let us take an example of Deparment and Employee. One department can have many employees and this is one of the best example of one to many relatonship. And again when we see from employee side, then it is many to one relationship.

hibernate-one-to-many-relationship

From sql perspective, table EMPLOYEES will have a foreign key constraint that will point to the primary key of table DEPARTMENTS and there can be multiple employees pointing to a single department.

Following is the sql for hibernate one to many relationships

CREATE TABLE departments ( RECORD_ID INT NOT NULL AUTO_INCREMENT, NAME VARCHAR(255), PRIMARY KEY (RECORD_ID) ) ENGINE=InnoDB; CREATE TABLE employees ( RECORD_ID INT NOT NULL AUTO_INCREMENT, AGE INT, NAME VARCHAR(255), DEPT_ID INT, PRIMARY KEY (RECORD_ID) ) ENGINE=InnoDB; ALTER TABLE employees ADD CONSTRAINT FK_j1ryo80krj2mrd97datx3hdry FOREIGN KEY (DEPT_ID) REFERENCES departments (RECORD_ID)

Environment Setup

1. JDK 7 2. Hibernate 4 3. Intellij Idea/ eclipse 4. MySql 5. Maven

Project Structure

We have 2 model classes - Department.java and Employee.java that has one to many relationship. We have Application.java that has a main method which will be used to start the application. We have hibernate.cfg.xml file that has all the hibernate configurations.

Maven Dependencies

Following are the maven dependencies required to include in pom.xml to get started.

pom.xml
<dependencies> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>4.3.11.Final</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.38</version> </dependency> <dependency> <groupId>org.javassist</groupId> <artifactId>javassist</artifactId> <version>3.18.0-GA</version> </dependency> </dependencies>

hibernate.cfg.xml

<hibernate-configuration> <session-factory> <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <property name="hibernate.connection.url">jdbc:mysql://localhost/test</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.connection.password">root</property> <property name="hibernate.hbm2ddl.auto">update</property> <property name="show_sql">false</property> <mapping class="com.devglan.model.Employee"/> <mapping class="com.devglan.model.Department"/> </session-factory> </hibernate-configuration>

Definig Hibernate Entities

As discussed above, we have 2 entities, Department and Employee. So, let us define them first and then we will discuss about the different annotations used in the one to many relationship. Following annotation configurations is for unidirectional relationship.

Employee.java
package com.devglan.model; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name = "EMPLOYEES") public class Employee { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "RECORD_ID") private Integer id; @Column(name = "NAME") private String name; @Column(name="AGE") private Integer age; //getters and setters goes here
Department.java
package com.devglan.model; import java.util.List; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.OneToMany; import javax.persistence.Table; @Entity @Table(name = "DEPARTMENTS") public class Department { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "RECORD_ID") private Integer id; @Column(name = "NAME") private String name; @OneToMany @JoinColumn(name ="DEPT_ID") private List emps; //getters and setters goes here

Let us discuss about unidirectional and bidirectional relationship based on above examples in next section

Unidirectional One to Many Relationships

Unidirectional relationship means the relationship between the entities can be traversed in a single direction. For example, in the above Department entity, Department.java has reference to Employee.java but Employee class does not relate to Department class in any manners. You can see @JoinColumn annotation is used in Department class though the foreign key will be created in EMPLOYEES table.

One thing to observe here is though the relationship is unidirectional, we are not using mappedBy attribute in the annotation @JoinColumn because associations marked as mappedBy must not define database mappings like @JoinTable or @JoinColumn.

In many cases, unidirectional relationship is preferred unless you require to traverse the entity graph from both side of relationship.

Bidirectional One to Many Relationships

In case of Bidirectional One to many relationship, you have freedom to traverse the relationship from both the direction. Either you can traverse Employee from Department side or you can traverse Department from Employee side. But above entity configurations is for unidirectional one to many relationship. Let us define bidirectional relationship now.

You require to have following changes in Department.java for bidirectional relations.

@OneToMany(mappedBy = "dept") private List emps;

Following changes are required in Employee.java. We have added @ManyToOne/span> here.

@ManyToOne @JoinColumn(name ="DEPT_ID") private Department dept;

Now let us define our Application.java that will make entries in EMPLOYEES and DEPARTMENT table

Application.java
package com.devglan.model; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.cfg.Configuration; public class Application { public static void main(String[] args) { createDepartment(); } public static SessionFactory getSessionFactory() { Configuration configuration = new Configuration().configure(); StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder() .applySettings(configuration.getProperties()); SessionFactory sessionFactory = configuration .buildSessionFactory(builder.build()); return sessionFactory; } public static void createDepartment() { System.out.println("****************Creating Department*************"); Department dept = new Department(); dept.setName("Science"); Employee emp1 = new Employee("John", 23); Employee emp2 = new Employee("Rohan", 25); dept.setEmps(Arrays.asList(emp1,emp2)); Session session = getSessionFactory().openSession(); session.beginTransaction(); session.save(dept); session.save(emp1); session.save(emp2); session.getTransaction().commit(); session.close(); System.out.println("Employee Created Successfully" + dept.toString()); } }

Optional Elements in OneToMany Annotation

There are many optional elements which can be used with annotations @OneToMany. Let us discuss them one by one.

targetEntity - If you are using java generics to define the collection, then this propery is optional. It denotes the entity class that is target of the association. e.g. @OneToMany(target = Employee.class)

cascade - It defines the flow of operations to associated entities. By default, none of the operations are cascaded. e.g. - @OneToMany(cascade = CascadeType.ALL)

fetch - By default fetch type is Lazy in all the relationship except for OneToOne. It defines whether the associated entities be fetched lazily or eagerly. e.g. - @OneToMany(fetch = FetchType.EAGER)

orphanRemoval - If this property is set to true, then cascade type remove is applied to entities that have been removed from the relationship. e.g. - @OneToMany(orphanRemoval = true)

mappedBy - mappedBy represent the entity that owns the relationship meaning the corresponding table that has foriegn key column and this element is specified on the non-owning side of the association.e.g. - @OneToMany(mappedBy = "dept")

Run Application

Run Application.java as a java application and you can see employee and department entries in the DB.

I hope this article served you whatever you were looking for. If you have anything that you want to add or share then please share it below in the comment section.

References

Hibernate Docs

One to Many Docs

Suggest more topics in suggestion section or write your own article and share with your colleagues.

Is this page helpful to you? Please give us your feedback below. We would love to hear your thoughts on these articles, it will help us improve further our learning process.

Further Reading: