Spring Boot One To Many Bidirectional Example (2024)
In this tutorial, we'll demonstrate how to create Spring Boot + JPA + One to Many Bidirectional mapping with MySQL database.
A one-to-many association in a relational database system connects two tables using a Foreign Key
field organization_id
such that the child table (employees
) record links
the Primary Key id
of the parent table (organization
) record.
Q: What is association mapping in JPA?
Ans:
An important main components of JPA and Hibernate is association mapping. It represent the relationship between domain model attributes with database tables attributes. This mapping enables the user to manage the relationship with ease by using JPQL or Criteria Queries.
Q: How many types of association mapping are there in Hibernate?
Ans:
The four ways that JPA and Hibernate provide the mapping of associations between objects are listed below. Both unidirectional and bidirectional association mappings are possible.
- Many-to-One
- One-to-One
- One-to-Many
- Many-to-Many
Refer detail implementation with source code for Spring Boot One To Many Unidirectional Example.
Q: What is one to many relationship in Spring JPA?
Ans:
One to many mapping describes the ability to map a single row in one table to multiple rows in another table. For example, consider an organization where we have employees. A company may have a lot of employees, hence this is a one to many mapping.
Q: What is a unidirectional and bidirectional relationship in Spring JPA?
Ans:
A bidirectional association enables us to retrieve information about the dependent object from both sides while a unidirectional relationship is only valid in one direction.
Also Refer Spring Boot Audit Logging Example to automatically store auditing information for each entity, such as created by, created date, modified by, and modified date using JPA.
Create Spring Boot application
Create Spring Boot application from Spring Initializr.
Project Structure
Add Dependencies
Add below dependencies for Web - spring-boot-starter-web
, JPA - spring-boot-starter-data-jpa
and MYSQL - mysql-connector-java
in 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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.techgeeknext</groupId>
<artifactId>spring-boot-one-to-many</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-boot-one-to-many</name>
<description>Spring Boot + One to Many Bidirectional Mapping Example</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Take a look at our suggested posts:
Application Properties
Add database connection details in application.properties
file.
spring.datasource.url=jdbc:mysql://localhost/organizationdb?createDatabaseIfNotExist=true&autoReconnect=true&useSSL=false
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.platform=mysql
spring.datasource.initialization-mode=always
## Hibernate Properties
# The SQL dialect makes Hibernate generate better SQL for the chosen database
# spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
# Hibernate ddl auto (create, create-drop, validate, update)
spring.jpa.hibernate.ddl-auto = update
For one to many mapping example, consider an organization having many employees.
Organization Data Model
- Create
Organization
class, containsid
andname
andSet of Employees
. - A One-to-Many mapping can be achieved by utilizing a
Set
java collection with no duplicate elements. - Hibernate is informed by the
mappedBy
attribute that theForeign Key
is controlled by the@ManyToOne
side. As a result, the associated object is managed by the child class rather than the parent class. FetchType.LAZY
is used in the@OneToMany
association. As default isEAGER
fetching which will be poor for performance.
package com.techgeeknext.model;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.ToString;
import javax.persistence.*;
import java.util.HashSet;
import java.util.Set;
@ToString
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "organization")
public class Organization {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "organization_seq_gen")
@SequenceGenerator(name = "organization_seq_gen", sequenceName = "org_seq")
private long id;
@Column(name = "name")
private String name;
@OneToMany(mappedBy = "organization", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JsonManagedReference
private Set<Employees> employees = new HashSet<>();
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<Employees> getEmployees() {
return employees;
}
public void setEmployees(Set<Employees> employees) {
this.employees = employees;
for (Employees emp : employees) {
emp.setOrganization(this);
}
}
}
Employees Data Model
- Create
Employees
class, containsid
,name
andOrganization
object. - The bidirectional relationship requires the provision of a
@ManyToOne
annotation by the child entity mapping, which is in charge of controlling the association. - Use
@JoinColumn
with the@ManyToOne
annotation. - The
@JoinColumn
annotation allows Hibernate to join the two database tables using theorganization_id
column in theemployees
table. FetchType.LAZY
is used in the@ManyToOne
association. As default isEAGER
fetching which will be poor for performance.
package com.techgeeknext.model;
import com.fasterxml.jackson.annotation.JsonBackReference;
import lombok.*;
import javax.persistence.*;
@Getter
@Setter
@ToString
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "employees")
public class Employees {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "employees_seq_gen")
@SequenceGenerator(name = "employees_seq_gen", sequenceName = "emp_seq")
private long id;
@Column(name = "name")
private String name;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "organization_id")
@JsonBackReference
private Organization organization;
}
Organization JPA Repository
Create OrganizationRepository
interface that extends JpaRepository
.
package com.techgeeknext.repository;
import com.techgeeknext.model.Organization;
import org.springframework.data.jpa.repository.JpaRepository;
public interface OrganizationRepository extends JpaRepository<Organization, Long> {
}
Employees JPA Repository
Create EmployeesRepository
interface that extends JpaRepository
.
package com.techgeeknext.repository;
import com.techgeeknext.model.Employees;
import org.springframework.data.jpa.repository.JpaRepository;
public interface EmployeesRepository extends JpaRepository<Employees, Long> {
}
Organization Controller
Create a rest endpoint to create an organization and assign employees in order to test JPA one-to-many mapping in the Spring Boot application.
package com.techgeeknext.controller;
import com.techgeeknext.model.Organization;
import com.techgeeknext.repository.OrganizationRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
//@CrossOrigin(origins = "http://localhost:3000") //open for specific port
@CrossOrigin() // open for all ports
@RestController
public class OrganizationController {
@Autowired
OrganizationRepository organizationRepository;
/**
* Create new organization and assign employees
*
* @param organization
* @return ResponseEntity
*/
@PostMapping("/org/assign")
public ResponseEntity<Organization> assignEmpToOrg(@RequestBody Organization organization) {
return new ResponseEntity<>(
organizationRepository.save(organization),
HttpStatus.CREATED);
}
}
Test Spring Boot JPA One To Many Bidirectional Example
- Start the Spring Boot Application by running
spring-boot:run
or by running main class. - Open Postman, use POST method with end point http://localhost:8080/org/assign and provide organization and employees details.
- Once the above records are generated, the following tables and data will be generated:
- Employees table with its data.
Refer Spring Boot JPA CRUD Example to implement all the CRUD rest endpoints with this example.
Download Source Code
The full source code for this article can be found below.
- Download it here - Spring Boot One To Many Bidirectional Example