Hibernate Self Join Annotations One To Many mapping example

Welcome to the Hibernate Tutorial Series. In previous tutorial we saw how to implement Many to Many relationship using Annotation mapping. In this tutorial we will modify the source code from previous Many To Many XML mapping tutorial and add JPA/Annotation support to it.

Self Join: One to Many
In a query, a table that is related to itself by two different fields. For example, an employee table can include the ID of a manager who is also in the same table.

A Self-Join or Self-Reference is basically one which has some sort of Parent/Child sturcture. We will see an example where we implement Self-Join in class of same type. For example Manager / Subordinates relationship.

Let us see how to implement Self Reference One-to-Many relationship in Hibernate using Annotation.

1. Create Database

For this example, we will MySQL database. We are using Manager / Subordinates relationship as a Self-Join One to Many mapping example. Each manager is an employee. Hence we implement a Parent/Child relationship in Employee enitity.

CREATE TABLE `employee` ( `employee_id` BIGINT(10) NOT NULL AUTO_INCREMENT, `firstname` VARCHAR(50) NULL DEFAULT NULL, `lastname` VARCHAR(50) NULL DEFAULT NULL, `manager_id` BIGINT(20) NULL DEFAULT NULL, PRIMARY KEY (`employee_id`), CONSTRAINT `FK_MANAGER` FOREIGN KEY (`manager_id`) REFERENCES `employee` (`employee_id`) )
Code language: SQL (Structured Query Language) (sql)

Here in Employee table, we defined a column MANAGER_ID which is mapped to the same table’s primary key. Thus for each employee we will store its manager’s id also. Manager will be yet another employee in this table.

2. Project Setup

Download the source code: Hibernate-many-to-many-annotation.zip (8 KB) and import the project in Eclipse. We will update the source code.

3. Update Hibernate Model Class

We will update Employee and Meeting model classes and add Annotations to map them with database table.

File: Employee.java

package net.viralpatel.hibernate; import java.util.HashSet; import java.util.Set; import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.OneToMany; import javax.persistence.Table; @Entity @Table(name="EMPLOYEE") public class Employee { @Id @Column(name="EMPLOYEE_ID") @GeneratedValue private Long employeeId; @Column(name="FIRSTNAME") private String firstname; @Column(name="LASTNAME") private String lastname; @ManyToOne(cascade={CascadeType.ALL}) @JoinColumn(name="manager_id") private Employee manager; @OneToMany(mappedBy="manager") private Set<Employee> subordinates = new HashSet<Employee>(); public Employee() { } public Employee(String firstname, String lastname) { this.firstname = firstname; this.lastname = lastname; } // Getter and Setter methods }
Code language: Java (java)

Note that in Employee entity class, we defined two new attributes: Employee manager and Set<Employee> subordinates. Attribute manager is mapped with @ManyToOne annotation and subordinates is mapped with @OneToMany. Also within @OneToMany attribute we defined mappedBy="manager" making manager as the relationship owner and thus which manages the foreign relationship within table.

Also the annotation @JoinColumn is defined on manager making it the relationship owner. @JoinColumn defines the joining column which in our case is manager_id.

4. Hibernate Configuration File

Edit Hibernate configuration file (hibernate.cfg.xml) and add mappings for Employee and Meeting classes. Following is the final hibernate.cfg.xml file:

File: hibernate.cfg.xml

<?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- Database connection settings --> <property name="connection.driver_class">com.mysql.jdbc.Driver</property> <property name="connection.url">jdbc:mysql://localhost:3306/tutorial</property> <property name="connection.username">root</property> <property name="connection.password"></property> <property name="connection.pool_size">1</property> <property name="dialect">org.hibernate.dialect.MySQLDialect</property> <property name="current_session_context_class">thread</property> <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property> <property name="show_sql">true</property> <property name="hbm2ddl.auto">validate</property> <mapping class="net.viralpatel.hibernate.Employee"/> </session-factory> </hibernate-configuration>
Code language: HTML, XML (xml)

5. Review Project Structure

Execute example

Execute following Main class to test Self Reference relational using Annotation.

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(); Employee manager1 = new Employee("Chuck", "Norris"); Employee employee1 = new Employee("Sergey", "Brin"); Employee employee2 = new Employee("Larry", "Page"); employee1.setManager(manager1); employee2.setManager(manager1); session.save(employee1); session.save(employee2); session.getTransaction().commit(); session.close(); } }
Code language: Java (java)

We created one manager “Chuck Norris” and two employees “Sergey Brin” and “Larry Page”. We set the manager details for each employees and saved the employee. Following are the sql statements generated by Hibernate.

Output:

Hibernate: insert into EMPLOYEE (FIRSTNAME, LASTNAME, manager_id) values (?, ?, ?) Hibernate: insert into EMPLOYEE (FIRSTNAME, LASTNAME, manager_id) values (?, ?, ?) Hibernate: insert into EMPLOYEE (FIRSTNAME, LASTNAME, manager_id) values (?, ?, ?)
Code language: SQL (Structured Query Language) (sql)

Self Join EMPLOYEE table

Download Source Code

Hibernate-self-reference-annotation.zip (8 KB)

View Comments

  • Hi , I m facing issue in deletion, when i delete employee it is deleting manager also.. can you tell what could be the issue..\

    Thanks in advance.

  • in the given scenario if i use
    [code language="java"] List<Employee> list = session.createQuery(" from Employee where employeeId="+2).list();[/code]

    i get the whole object graph of [Chuck->Sergey,Chuck->Larry] but if i want to load the partial object graph & work on that only [Chuck->Sergey] then what needs to be done ? (I don't want Larry to be present in the whole relation i have fetched)..

  • Why do we need the
    [code language="java"]
    @OneToMany(mappedBy = &quot;manager&quot;)
    private Set&lt;Employee&gt; subordinates = new HashSet&lt;Employee&gt;();
    [/code]
    As we are not using this anywhere in main method as well, the code is running as it required if we remove this code.
    So, what is the use and meaning of using these statements in this example?

  • Great article!
    But it doesn't work this way for me.
    I have to add the employees to the manager and then persist the manager will write the 3 lines in the db.
    [code language="java"]
    manager1.getSubordinates().add(employee1);
    manager1.getSubordinates().add(employee2);
    session.save(manager1);
    [/code]

    Finally, the result is the same.

  • I am newbie so my question might be silly,
    You haven't saved the Manager before saving Employee.
    Does it save the manager while first employee is saved?

Recent Posts

  • Java

Java URL Encoder/Decoder Example

Java URL Encoder/Decoder Example - In this tutorial we will see how to URL encode/decode…

4 years ago
  • General

How to Show Multiple Examples in OpenAPI Spec

Show Multiple Examples in OpenAPI - OpenAPI (aka Swagger) Specifications has become a defecto standard…

4 years ago
  • General

How to Run Local WordPress using Docker

Local WordPress using Docker - Running a local WordPress development environment is crucial for testing…

4 years ago
  • Java

Create and Validate JWT Token in Java using JJWT

1. JWT Token Overview JSON Web Token (JWT) is an open standard defines a compact…

4 years ago
  • Spring Boot

Spring Boot GraphQL Subscription Realtime API

GraphQL Subscription provides a great way of building real-time API. In this tutorial we will…

4 years ago
  • Spring Boot

Spring Boot DynamoDB Integration Test using Testcontainers

1. Overview Spring Boot Webflux DynamoDB Integration tests - In this tutorial we will see…

4 years ago