hibernate

Hibernate Foreign Key Example

1. Introduction

In this post, we feature a comprehensive Example on Hibernate Foreign Key. Foreign key refers to single column or group of columns in table that link data present in another table through its primary key. A Foreign key can’t exist without its parent key but viceversa is not true.

Example – A Menu can have submenus. It can be represented in tabular form as shown below where column MENU_ID is Primary key of T_MENU table and it is acting as Foreign Key (link between both tables) for T_SUBMENU table:

Hibernate Foreign Key - Illustration
Foreign Key Illustration

 

 
Java Persistance Specifications provide different ways to create Foreign Key mappings as mentioned below:

1 – Using Association Mappings
2 – By Saving Collections using @ElementCollection

In this article we will show Foreign Key Creation using One to Many bi-directional Association Mapping.

Association Mapping – It is a feature provided by JPA to link two tables using below associations. Each Association can be Uni-Directional or Bi-Directional.

AssociationExample
One to OneOne Person can have One Unique Identification Number
One to ManyOne Menu can have Many Sub-Menu
Many to OneMany Sub-Menu can have One Parent Menu (Reverse of Many to One)
Many to ManyOne Student can enrol for many courses and a course can be enrolled by many students.

2. Technologies Used

We will be building this project from scratch using following tools and technologies:

  • Eclipse
  • Spring Boot 1.5.10
  • Maven
  • Oracle
  • Hibernate
  • Java 8 or above

3. Create Project

We are creating Spring Boot project using Spring initializer. Steps are mentioned below:
1 – Go to http://start.spring.io/
2 – Select the following:

Hibernate Foreign Key - Spring Boot Project Initializr
Spring Boot Project Initializr

3 – Click on Generate Project button that will download a ready to deploy Maven project.
4 – Extract the downloaded Zip folder and paste it into your workspace.
5 – Open Eclipse -> File -> Import -> Maven -> Existing Maven Projects and select your project. Check the box(Add project(s) to working set). Finish

This spring project is ready to deploy and you can run it as Java Application in Eclipse. Now we will build our One To Many Mapping Example. For Simplicity, we’ll be creating Service, Repository and Model classes in same package – com.example.hibernateExample.

3.1 Project Configurations

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.example</groupId>
<artifactId>hibernateExample</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>

<name>hibernateExample</name>

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.16.BUILD-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

Dependencies used in pom.xml: Spring Boot MVC(spring-boot-starter-web), Hibernate (spring-boot-starter-data-jpa) and jaxb-api.

application.properties

# create and drop tables and sequences, loads import.sql
spring.jpa.hibernate.ddl-auto=create-drop

# Oracle settings
spring.datasource.url=jdbc:oracle:thin:@localhost:1521:XE
spring.datasource.username=
spring.datasource.password=
spring.datasource.driver.class=oracle.jdbc.driver.OracleDriver
 
# logging
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - %msg%n
logging.level.org.hibernate.SQL=debug

application.properties file is present in src/main/resources folder of a Spring Boot project. We are doing Hibernate Configurations here using Oracle JDBC driver (Since Oracle restricts automatic download of OJDBC dependency by Maven, one need to explicitly download ojdbc6.jar/ojdbc7.jar from Oracle’s site and need to include it in ClassPath)

3.2 Model Classes – MainMenu and SubMenu

In this section, we will design our model or entity classes using JPA and Hibernate provided annotations. Hibernate framework will be using these annotations to create tables and their Foreign Key Relationship in database. Variables of Entity class will be created as Columns in database table.

MainMenu.java

package com.example.hibernateExample;
import java.io.Serializable;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
@Table(name = "T_Menu")
public class MainMenu implements Serializable{
	
	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	private int id;
	
	private String description;
	
	@OneToMany(mappedBy="mainMenu", cascade = CascadeType.ALL)
	Set subMenu = new HashSet();

	public MainMenu() {	
	}
	
	public MainMenu(String description) {
		this.description = description;
	}

// Getters and Setters (Omitted for brevity)

MainMenu class is One(Reference) side of relationship and SubMenu class represents Many(owning) side of relationship as ‘One Menu can have many Sub Menu’. In Database terminology, the table that has foreign key is Owner of association mapping. Let’s understand few annotations in detail which are used by Hibernate framework to create and manage Entity classes.
Line 16: @Entity denotes the class as Entity class. Hibernate will create instance of such classes and also create table corresponding to it in database.
Line 17: @Table is used to specify details of the table that is going to be created in database corresponding to entity class. name attribute of this annotation allow programmer to create a table with desired name in database. If we don’t specify this annotation, table name will be same as entity class name.
Line 20: @Id specify the variable as Primary key column for database table.
Line 21: @GeneratedValue specify the Generation strategy for Primary Key.
Line 26: mappedBy is used with @OnetoMany side of association. It indicates that the entity in this side is the inverse of the relationship, and the owner resides in the “other” entity. It is used to make a relationship Bi-directional, that means the SubMenu class can be persisted or fetched through Menu class as well.

mainMenu in mappedBy="mainMenu" is the ManyToOne annotated field/variable of SubMenu class as shown below:

Hibernate Foreign Key - Association Mapping
Association Mapping

CascadeType.ALL will perform all EntityManager operations (PERSIST, REMOVE, REFRESH, MERGE, DETACH) to the related entities/ collection e.g when Menu will be Persisted, SubMenu will also be Persisted.

SubMenu.java

package com.example.hibernateExample;

import java.io.Serializable;

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.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name = "T_SubMenu")
public class SubMenu implements Serializable{
	
	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	private int id;
	
	@Column(name="SUBMENU_DESC", nullable=false, length=50)
	private String description;
	
	
	@ManyToOne
	@JoinColumn(name ="FK_MainMenuId")
	private MainMenu mainMenu;
	
	public SubMenu() {
		
	}
	
	public SubMenu(String description, MainMenu mainMenu) {
		this.description = description;
		this.mainMenu = mainMenu;
	}
// Getters and Setters (Omitted for brevity)

Entity class SubMenu will be used by Hibernate to create T_Submenu table in database. @JoinColumn annotation in line 27 indicates that this entity is the owner of the relationship (which will contain Foreign Key in Database perspective). This annotation is always used with @ManyToOne side of association. name attribute is used to give logical name to Foreign Key column, though it is not mandatory.

3.3 Repository Interface

MainMenuRepository.java

package com.example.hibernateExample;

import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface MainMenuRepository extends CrudRepository<MainMenu, Integer>{
	
}

In this section we are creating MainMenuRepository interface that is a Marker interface(which doesn’t define any methods). When using Spring Data we need to define a Repository interface corresponding to each domain Entity. It will be extending Spring Data’s CrudRepository interface which declares standard CRUD operations that can be performed on an entity. Use of CrudRepository interface will prevent us from writing a lot of boilerplate code to access data source, writing SQL queries, Result Set etc. It will accept two parameters:
1 – Entity class corresponding to the Marker interface.
2 – Data type of Primary key defined within Entity class.

3.4 Runner

HibernateExampleApplication.java

package com.example.hibernateExample;

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;


@SpringBootApplication
public class HibernateExampleApplication implements CommandLineRunner
{
	 @Autowired
	   MenuService menuService;
	 
    public static void main( String[] args )
    {
        SpringApplication.run(App.class, args);
    }

        @Override
	public void run(String... args) throws Exception {
		menuService.addMenu();
	}
}

HibernateExampleApplication java class will implement CommandLineRunner interface. This class is annotated with @SpringBootApplication that is equivalent of using @Configuration, @EnableAutoConfiguration, and @ComponentScan. We will be adding new Menus and subMenus in addMenu() of service class, which is invoked in overrided run() of CommandLineRunner interface.

3.5 Service Layer

In this section we will be creating new Menus and their Sub-Menus using methods provided by Spring Data’s CrudRepository interface. The newly created Menus and their associated Sub-Menus will be added as rows in T_menu and T_submenu table by Hibernate framework.

MenuService.java

package com.example.hibernateExample;

public interface MenuService {
	public void addMenu();
}

MenuServiceImpl.java

package com.example.hibernateExample;

import java.util.HashSet;
import java.util.Set;
import javax.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class MenuServiceImpl implements MenuService{
	
	@Autowired
	MainMenuRepository mainMenuRepository;

	@Transactional
	public void addMenu(){
		// For User MainMenu
		 MainMenu menu1 = new MainMenu("User");
		 //Creating sub-menus for user
		 Set subMenu1 = new HashSet();
		 subMenu1.add(new SubMenu("Manager", menu1));
		 subMenu1.add(new SubMenu("Administrator", menu1));
		 subMenu1.add(new SubMenu("Student", menu1));
		 menu1.setSubMenu(subMenu1);
		 
		// For Courses MainMenu
				 MainMenu menu2 = new MainMenu("Course");
				 //Creating sub-menus for user
				 Set subMenu2 = new HashSet();
				 subMenu2.add(new SubMenu("B-Tech", menu2));
				 subMenu2.add(new SubMenu("BCA", menu2));
				 subMenu2.add(new SubMenu("MBA", menu2));
				 menu2.setSubMenu(subMenu2);
				 
		// For Department MainMenu
				 MainMenu menu3 = new MainMenu("Department");
				 //Creating sub-menus for user
				 Set subMenu3 = new HashSet();
				 subMenu3.add(new SubMenu("Accounts", menu3));
				 subMenu3.add(new SubMenu("Information Technology", menu3));
				 subMenu3.add(new SubMenu("Sports", menu3));
				 menu3.setSubMenu(subMenu3);
		
	   //Save MainMenu  
		 Set mainMenu = new HashSet();
		 mainMenu.add(menu1);
		 mainMenu.add(menu2);
		 mainMenu.add(menu3);
	   mainMenuRepository.save(mainMenu);
	     	    	
	}
}

addMenu() of MenuServiceImpl class is adding 3 MainMenu named as Course, Department and User and their submenus using CrudRepository’s save().
On Executing this project as a Java Application in Eclipse, we will get following output where FK_MAIN_MENU_ID is foreign key in T_submenu table:

ID DESCRIPTION
1Department
5Course
9User

 

IDSUBMENU_DESCFK_MAIN_MENU_ID
2Sports1
3Information Technology1
4Accounts1
6B-Tech5
7BCA5
8MBA5
10Manager9
11Student9
12Administrator9

4. Summary

To Summarize, we have created a Spring Boot project that is adding 3 mainMenu in T_menu table i.e Course, Department and User. Each mainMenu can have multiple submenu which are stored in T_submenu table. Both these tables are linked through a Foreign Key named as FK_MAIN_MENU_ID which is created through One To Many Bidirectional mapping between MainMenu.java and SubMenu.java Entity classes.

5. Download the Source Code

This was an example of creating a Hibernate Foreign Key.

Download
You can download the full source code of this example here: hibernateExample.zip

Shagun Mittal

Shagun is an enthusiastic Java developer with 5 + years of Industry experience in various Java and Web technologies. She is a certified Java Programmer and has worked extensively with other programming languages and framework, such as Hibernate, Spring MVC, Spring Boot, RDBMS, Unix, etc. As part of delivery services she has created and implemented efficient applications and programs in various industries, including insurance, retail, public sector, telecommunication etc.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

3 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Michael Murphy
Michael Murphy
5 years ago

I have no idea if you guys monitor these comments but I just wanted to say you’ve saved me with this tutorial, I was having trouble finding something to explain this simple functionality! This was very clear, and very easy to extend to my own project!

Kemal
Kemal
3 years ago
at line 
  mainMenuRepository.save(mainMenu);

I get the error:
Inferred type ‘S’ for type parameter ‘S’ is not within its bound; should extend ‘com.example.hibernateExample.MainMenu’

Vivek Mishra
Vivek Mishra
2 years ago

As I can see above in introduction
Menu can have sub_Menus
but what if we have this case

two different menus having atleast one common sub-menu

This particular confiiguration will not work

Back to top button