Spring Boot One-to-Many Mapping

Introduction

In this chapter, we will explore how to implement a one-to-many relationship in a Spring Boot application by building an Employee Management Project. We will create entities for Employee and Department, configure the one-to-many relationship between them, and demonstrate how to perform CRUD operations.

Table of Contents

  1. Introduction
  2. Create and Setup Spring Boot Project in IntelliJ IDEA
  3. Configure H2 Database
  4. Create Employee and Department Entities
  5. Configure One-to-Many Relationship
  6. Create Employee Repository
  7. Create Department Repository
  8. Create Service Layer
    • EmployeeService
    • EmployeeServiceImpl
    • DepartmentService
    • DepartmentServiceImpl
  9. Create EmployeeController
  10. Create DepartmentController
  11. Test the Application
  12. Conclusion

Create and Setup Spring Boot Project in IntelliJ IDEA

Create a New Spring Boot Project

  1. Open Spring Initializr:

  2. Configure Project Metadata:

    • Project: Maven Project
    • Language: Java
    • Spring Boot: 3.2.0
    • Group: com.example
    • Artifact: employee-management
    • Name: employee-management
    • Description: Employee Management System with One-to-Many Mapping
    • Package name: com.example.employeemanagement
    • Packaging: Jar
    • Java: 17 (or the latest version available)
  3. Add Dependencies:

    • Spring Web
    • Spring Data JPA
    • H2 Database
  4. Generate the Project:

    • Click "Generate" to download the project as a ZIP file.
  5. Import Project into IntelliJ IDEA:

    • Open IntelliJ IDEA.
    • Click on "Open" and navigate to the downloaded ZIP file.
    • Extract the ZIP file and import the project.

Explanation

  • Spring Initializr: A web-based tool provided by Spring to bootstrap a new Spring Boot project with dependencies and configurations.
  • Group and Artifact: Define the project’s Maven coordinates.
  • Dependencies: Adding dependencies ensures that the necessary libraries are included in the project for web development, JPA, and H2 database connectivity.

Configure H2 Database

Update application.properties

  1. Open application.properties:

    • Navigate to src/main/resources/application.properties.
  2. Add H2 Database Configuration:

    • Add the following properties to configure the H2 database connection:
spring.datasource.url=jdbc:h2:mem:employeedb spring.datasource.driverClassName=org.h2.Driver spring.datasource.username=sa spring.datasource.password=password spring.jpa.hibernate.ddl-auto=update spring.h2.console.enabled=true spring.h2.console.path=/h2-console 

Explanation

  • spring.datasource.url: The JDBC URL to connect to the H2 database in memory.
  • spring.datasource.driverClassName: The driver class name for H2 database.
  • spring.datasource.username: The username to connect to the H2 database.
  • spring.datasource.password: The password to connect to the H2 database.
  • spring.jpa.hibernate.ddl-auto: Specifies the Hibernate DDL mode. Setting it to update automatically updates the database schema based on the entity mappings.
  • spring.h2.console.enabled: Enables the H2 database console for easy access to the database through a web browser.
  • spring.h2.console.path: Specifies the path to access the H2 console.

Create Employee and Department Entities

Create the Employee Class

  1. Create a New Package:

    • In the src/main/java/com/example/employeemanagement directory, create a new package named model.
  2. Create the Employee Class:

    • Inside the model package, create a new class named Employee.
    • Add the following code to the Employee class:
package com.example.employeemanagement.model; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.ManyToOne; @Entity public class Employee { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String firstName; private String lastName; private String email; @ManyToOne private Department department; // Constructors public Employee() {} public Employee(String firstName, String lastName, String email) { this.firstName = firstName; this.lastName = lastName; this.email = email; } // Getters and Setters public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public Department getDepartment() { return department; } public void setDepartment(Department department) { this.department = department; } } 

Create the Department Class

  1. Create the Department Class:
    • Inside the model package, create a new class named Department.
    • Add the following code to the Department class:
package com.example.employeemanagement.model; import jakarta.persistence.CascadeType; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.OneToMany; import java.util.ArrayList; import java.util.List; @Entity public class Department { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; @OneToMany(mappedBy = "department", cascade = CascadeType.ALL) private List<Employee> employees = new ArrayList<>(); // Constructors public Department() {} public Department(String name) { this.name = name; } // Getters and Setters 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 List<Employee> getEmployees() { return employees; } public void setEmployees(List<Employee> employees) { this.employees = employees; } // Utility method to add employee public void addEmployee(Employee employee) { employees.add(employee); employee.setDepartment(this); } } 

Explanation

  • @Entity: Specifies that the class is an entity and is mapped to a database table.
  • @Id: Specifies the primary key of the entity.
  • @GeneratedValue: Specifies how the primary key should be generated. GenerationType.IDENTITY indicates that the primary key is auto-incremented.
  • @ManyToOne: Specifies a many-to-one relationship between the Employee and Department entities.
  • @OneToMany: Specifies a one-to-many relationship between the Department and Employee entities.
  • @CascadeType.ALL: Specifies that all cascade types (persist, merge, remove, refresh, detach) should be applied.
  • Utility method: addEmployee is a utility method to add an employee to a department and set the department for the employee.

Create Employee Repository

Create the EmployeeRepository Interface

  1. Create a New Package:

    • In the src/main/java/com/example/employeemanagement directory, create a new package named repository.
  2. Create the EmployeeRepository Interface:

    • Inside the repository package, create a new interface named EmployeeRepository.
    • Add the following code to the EmployeeRepository interface:
package com.example.employeemanagement.repository; import com.example.employeemanagement.model.Employee; import org.springframework.data.jpa.repository.JpaRepository; public interface EmployeeRepository extends JpaRepository<Employee, Long> { } 

Explanation

  • JpaRepository: The EmployeeRepository interface extends JpaRepository, providing CRUD operations for the Employee entity. The JpaRepository interface includes methods like save(), findById(), findAll(), deleteById(), etc.
  • Generics: The JpaRepository interface takes two parameters: the entity type (Employee) and the type of its primary key (Long).

Create Department Repository

Create the DepartmentRepository Interface

  1. Create the DepartmentRepository Interface:
    • Inside the repository package, create a new interface named DepartmentRepository.
    • Add the following code to the DepartmentRepository interface:
package com.example.employeemanagement.repository; import com.example.employeemanagement.model.Department; import org.springframework.data.jpa.repository.JpaRepository; public interface Department Repository extends JpaRepository<Department, Long> { } 

Explanation

  • JpaRepository: The DepartmentRepository interface extends JpaRepository, providing CRUD operations for the Department entity. The JpaRepository interface includes methods like save(), findById(), findAll(), deleteById(), etc.
  • Generics: The JpaRepository interface takes two parameters: the entity type (Department) and the type of its primary key (Long).

Create Service Layer

Create EmployeeService Interface

  1. Create a New Package:

    • In the src/main/java/com/example/employeemanagement directory, create a new package named service.
  2. Create the EmployeeService Interface:

    • Inside the service package, create a new interface named EmployeeService.
    • Add the following code to the EmployeeService interface:
package com.example.employeemanagement.service; import com.example.employeemanagement.model.Employee; import java.util.List; public interface EmployeeService { Employee saveEmployee(Employee employee); Employee getEmployeeById(Long id); List<Employee> getAllEmployees(); Employee updateEmployee(Long id, Employee employeeDetails); void deleteEmployee(Long id); } 

Explanation

  • Service Interface: Defines the contract for the service layer. It includes methods for saving, retrieving, updating, and deleting employees.

Create EmployeeServiceImpl Class

  1. Create the EmployeeServiceImpl Class:
    • Inside the service package, create a new class named EmployeeServiceImpl.
    • Add the following code to the EmployeeServiceImpl class:
package com.example.employeemanagement.service; import com.example.employeemanagement.model.Employee; import com.example.employeemanagement.repository.EmployeeRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; @Service public class EmployeeServiceImpl implements EmployeeService { @Autowired private EmployeeRepository employeeRepository; @Override public Employee saveEmployee(Employee employee) { return employeeRepository.save(employee); } @Override public Employee getEmployeeById(Long id) { return employeeRepository.findById(id) .orElseThrow(() -> new RuntimeException("Employee not found with id: " + id)); } @Override public List<Employee> getAllEmployees() { return employeeRepository.findAll(); } @Override public Employee updateEmployee(Long id, Employee employeeDetails) { Employee employee = employeeRepository.findById(id) .orElseThrow(() -> new RuntimeException("Employee not found with id: " + id)); employee.setFirstName(employeeDetails.getFirstName()); employee.setLastName(employeeDetails.getLastName()); employee.setEmail(employeeDetails.getEmail()); employee.setDepartment(employeeDetails.getDepartment()); return employeeRepository.save(employee); } @Override public void deleteEmployee(Long id) { Employee employee = employeeRepository.findById(id) .orElseThrow(() -> new RuntimeException("Employee not found with id: " + id)); employeeRepository.delete(employee); } } 

Explanation

  • @Service: Indicates that this class is a service component in the Spring context.
  • EmployeeRepository: The EmployeeRepository instance is injected into the service class to interact with the database.
  • Exception Handling: The getEmployeeById, updateEmployee, and deleteEmployee methods throw a RuntimeException if the employee is not found.

Create DepartmentService Interface

  1. Create the DepartmentService Interface:
    • Inside the service package, create a new interface named DepartmentService.
    • Add the following code to the DepartmentService interface:
package com.example.employeemanagement.service; import com.example.employeemanagement.model.Department; import java.util.List; public interface DepartmentService { Department saveDepartment(Department department); Department getDepartmentById(Long id); List<Department> getAllDepartments(); Department updateDepartment(Long id, Department departmentDetails); void deleteDepartment(Long id); } 

Explanation

  • Service Interface: Defines the contract for the service layer. It includes methods for saving, retrieving, updating, and deleting departments.

Create DepartmentServiceImpl Class

  1. Create the DepartmentServiceImpl Class:
    • Inside the service package, create a new class named DepartmentServiceImpl.
    • Add the following code to the DepartmentServiceImpl class:
package com.example.employeemanagement.service; import com.example.employeemanagement.model.Department; import com.example.employeemanagement.repository.DepartmentRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; @Service public class DepartmentServiceImpl implements DepartmentService { @Autowired private DepartmentRepository departmentRepository; @Override public Department saveDepartment(Department department) { return departmentRepository.save(department); } @Override public Department getDepartmentById(Long id) { return departmentRepository.findById(id) .orElseThrow(() -> new RuntimeException("Department not found with id: " + id)); } @Override public List<Department> getAllDepartments() { return departmentRepository.findAll(); } @Override public Department updateDepartment(Long id, Department departmentDetails) { Department department = departmentRepository.findById(id) .orElseThrow(() -> new RuntimeException("Department not found with id: " + id)); department.setName(departmentDetails.getName()); department.setEmployees(departmentDetails.getEmployees()); return departmentRepository.save(department); } @Override public void deleteDepartment(Long id) { Department department = departmentRepository.findById(id) .orElseThrow(() -> new RuntimeException("Department not found with id: " + id)); departmentRepository.delete(department); } } 

Explanation

  • @Service: Indicates that this class is a service component in the Spring context.
  • DepartmentRepository: The DepartmentRepository instance is injected into the service class to interact with the database.
  • Exception Handling: The getDepartmentById, updateDepartment, and deleteDepartment methods throw a RuntimeException if the department is not found.

Create EmployeeController

Create the EmployeeController Class

  1. Create a New Package:

    • In the src/main/java/com/example/employeemanagement directory, create a new package named controller.
  2. Create the EmployeeController Class:

    • Inside the controller package, create a new class named EmployeeController.
    • Add the following code to the EmployeeController class:
package com.example.employeemanagement.controller; import com.example.employeemanagement.model.Employee; import com.example.employeemanagement.service.EmployeeService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.util.List; @RestController @RequestMapping("/api/employees") public class EmployeeController { @Autowired private EmployeeService employeeService; @PostMapping public ResponseEntity<Employee> saveEmployee(@RequestBody Employee employee) { Employee savedEmployee = employeeService.saveEmployee(employee); return new ResponseEntity<>(savedEmployee, HttpStatus.CREATED); } @GetMapping("/{id}") public ResponseEntity<Employee> getEmployeeById(@PathVariable Long id) { Employee employee = employeeService.getEmployeeById(id); return new ResponseEntity<>(employee, HttpStatus.OK); } @GetMapping public ResponseEntity<List<Employee>> getAllEmployees() { List<Employee> employees = employeeService.getAllEmployees(); return new ResponseEntity<>(employees, HttpStatus.OK); } @PutMapping("/{id}") public ResponseEntity<Employee> updateEmployee(@PathVariable Long id, @RequestBody Employee employeeDetails) { Employee updatedEmployee = employeeService.updateEmployee(id, employeeDetails); return new ResponseEntity<>(updatedEmployee, HttpStatus.OK); } @DeleteMapping("/{id}") public ResponseEntity<Void> deleteEmployee(@PathVariable Long id) { employeeService.deleteEmployee(id); return new ResponseEntity<>(HttpStatus.NO_CONTENT); } } 

Explanation

  • @RestController: Indicates that this class is a REST controller.
  • @RequestMapping("/api/employees"): Maps HTTP requests to /api/employees to methods in this controller.
  • @PostMapping: Handles HTTP POST requests to save an employee.
  • @GetMapping("/{id}"): Handles HTTP GET requests to retrieve an employee by ID.
  • @GetMapping: Handles HTTP GET requests to retrieve all employees.
  • @PutMapping("/{id}"): Handles HTTP PUT requests to update an employee’s details.
  • @DeleteMapping("/{id}"): Handles HTTP DELETE requests to delete an employee by ID.

Create DepartmentController

Create the DepartmentController Class

  1. Create the DepartmentController Class:
    • Inside the controller package, create a new class named DepartmentController.
    • Add the following code to the DepartmentController class:
package com.example.employeemanagement.controller; import com.example.employeemanagement .model.Department; import com.example.employeemanagement.service.DepartmentService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.util.List; @RestController @RequestMapping("/api/departments") public class DepartmentController { @Autowired private DepartmentService departmentService; @PostMapping public ResponseEntity<Department> saveDepartment(@RequestBody Department department) { Department savedDepartment = departmentService.saveDepartment(department); return new ResponseEntity<>(savedDepartment, HttpStatus.CREATED); } @GetMapping("/{id}") public ResponseEntity<Department> getDepartmentById(@PathVariable Long id) { Department department = departmentService.getDepartmentById(id); return new ResponseEntity<>(department, HttpStatus.OK); } @GetMapping public ResponseEntity<List<Department>> getAllDepartments() { List<Department> departments = departmentService.getAllDepartments(); return new ResponseEntity<>(departments, HttpStatus.OK); } @PutMapping("/{id}") public ResponseEntity<Department> updateDepartment(@PathVariable Long id, @RequestBody Department departmentDetails) { Department updatedDepartment = departmentService.updateDepartment(id, departmentDetails); return new ResponseEntity<>(updatedDepartment, HttpStatus.OK); } @DeleteMapping("/{id}") public ResponseEntity<Void> deleteDepartment(@PathVariable Long id) { departmentService.deleteDepartment(id); return new ResponseEntity<>(HttpStatus.NO_CONTENT); } } 

Explanation

  • @RestController: Indicates that this class is a REST controller.
  • @RequestMapping("/api/departments"): Maps HTTP requests to /api/departments to methods in this controller.
  • @PostMapping: Handles HTTP POST requests to save a department.
  • @GetMapping("/{id}"): Handles HTTP GET requests to retrieve a department by ID.
  • @GetMapping: Handles HTTP GET requests to retrieve all departments.
  • @PutMapping("/{id}"): Handles HTTP PUT requests to update a department’s details.
  • @DeleteMapping("/{id}"): Handles HTTP DELETE requests to delete a department by ID.

Test the Application

Run the Application

  1. Run the Application:
    • In IntelliJ IDEA, run the EmployeeManagementApplication class.

Access the Application

  1. Open Web Browser:

    • Open a web browser and go to http://localhost:8080/api/employees to manage employees.
    • Open a web browser and go to http://localhost:8080/api/departments to manage departments.
  2. Verify the Application:

    • Verify that you can perform CRUD operations on employees and departments, ensuring that the one-to-many relationship is correctly configured and functioning.

Conclusion

In this chapter, we built an Employee Management System project using Spring Boot with a one-to-many relationship between Employee and Department entities. We configured the H2 database, created entities and repositories, and demonstrated how to perform CRUD operations through a RESTful API. Each step was explained in detail to help you understand how to implement one-to-many relationships in a Spring Boot application.

Leave a Comment

Scroll to Top