Spring Boot One-to-One Mapping

Introduction

In this chapter, we will explore how to implement a one-to-one relationship in a Spring Boot application by building a User Management Project. We will create entities for User and Profile, configure the one-to-one 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 User and Profile Entities
  5. Configure One-to-One Relationship
  6. Create User Repository
  7. Create Profile Repository
  8. Create Service Layer
    • UserService
    • UserServiceImpl
  9. Create UserController
  10. Test the Application
  11. 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: user-management
    • Name: user-management
    • Description: User Management System with One-to-One Mapping
    • Package name: com.example.usermanagement
    • 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:userdb
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 User and Profile Entities

Create the User Class

  1. Create a New Package:
    • In the src/main/java/com/example/usermanagement directory, create a new package named model.
  2. Create the User Class:
    • Inside the model package, create a new class named User.
    • Add the following code to the User class:
package com.example.usermanagement.model;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.OneToOne;

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String username;
    private String password;

    @OneToOne(mappedBy = "user")
    private Profile profile;

    // Constructors
    public User() {}

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }

    // Getters and Setters
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Profile getProfile() {
        return profile;
    }

    public void setProfile(Profile profile) {
        this.profile = profile;
    }
}

Create the Profile Class

  1. Create the Profile Class:
    • Inside the model package, create a new class named Profile.
    • Add the following code to the Profile class:
package com.example.usermanagement.model;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.OneToOne;

@Entity
public class Profile {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String firstName;
    private String lastName;
    private String email;

    @OneToOne
    @JoinColumn(name = "user_id")
    private User user;

    // Constructors
    public Profile() {}

    public Profile(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 User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }
}

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.
  • @OneToOne: Specifies a one-to-one relationship between the User and Profile entities.
  • @JoinColumn: Specifies the foreign key column in the Profile table that references the primary key of the User table.

Create User Repository

Create the UserRepository Interface

  1. Create a New Package:
    • In the src/main/java/com/example/usermanagement directory, create a new package named repository.
  2. Create the UserRepository Interface:
    • Inside the repository package, create a new interface named UserRepository.
    • Add the following code to the UserRepository interface:
package com.example.usermanagement.repository;

import com.example.usermanagement.model.User;
import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<User, Long> {
}

Explanation

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

Create Profile Repository

Create the ProfileRepository Interface

  1. Create a New Package:
    • In the src/main/java/com/example/usermanagement directory, create a new package named repository.
  2. Create the ProfileRepository Interface:
    • Inside the repository package, create a new interface named ProfileRepository.
    • Add the following code to the ProfileRepository interface:
package com.example.usermanagement.repository;

import com.example.usermanagement.model.Profile;
import org.springframework.data.jpa.repository.JpaRepository;

public interface ProfileRepository extends JpaRepository<Profile, Long> {
}

Explanation

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

Create Service Layer

Create UserService Interface

  1. Create a New Package:
    • In the src/main/java/com/example/usermanagement directory, create a new package named service.
  2. Create the UserService Interface:
    • Inside the service package, create a new interface named UserService.
    • Add the following code to the UserService interface:
package com.example.usermanagement.service;

import com.example.usermanagement.model.User;
import java.util.List;

public interface UserService {
    User saveUser(User user);
    User getUserById(Long id);
    List<User> getAllUsers();
    User updateUser(Long id, User userDetails);
    void deleteUser(Long id);
}

Explanation

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

Create UserServiceImpl Class

  1. Create the UserServiceImpl Class:
    • Inside the service package, create a new class named UserServiceImpl.
    • Add the following code to the UserServiceImpl class:
package com.example.usermanagement.service;

import com.example.usermanagement.model.User;
import com.example.usermanagement.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserRepository userRepository;

    @Override
    public User saveUser(User user) {
        return userRepository.save(user);
    }

    @Override
    public User getUserById(Long id) {
        return userRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("User not found with id: " + id));
    }

    @Override
    public List<User> getAllUsers() {
        return userRepository.findAll();
    }

    @Override
    public User updateUser(Long id, User userDetails) {
        User user = userRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("User not found with id: " + id));

        user.setUsername(userDetails.getUsername());
        user.setPassword(userDetails.getPassword());
        user.setProfile(userDetails.getProfile());

        return userRepository.save(user);
    }

    @Override
    public void deleteUser(Long id) {
        User user = userRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("User not found with id: " + id));

        userRepository.delete(user);
    }
}

Explanation

  • @Service: Indicates that this class is a service component in the Spring context.
  • UserRepository: The UserRepository instance is injected into the service class to interact with the database.
  • Exception Handling: The getUserById, updateUser, and deleteUser methods throw a RuntimeException if the user is not found.

Create UserController

Create the UserController Class

  1. Create a New Package:
    • In the src/main/java/com/example/usermanagement directory, create a new package named controller.
  2. Create the UserController Class:
    • Inside the controller package, create a new class named UserController.
    • Add the following code to the UserController class:
package com.example.usermanagement.controller;

import com.example.usermanagement.model.User;
import com.example.usermanagement.service.UserService;
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/users")
public class UserController {

    @Autowired
    private UserService userService;

    @PostMapping
    public ResponseEntity<User> saveUser(@RequestBody User user) {
        User savedUser = userService.saveUser(user);
        return new ResponseEntity<>(savedUser, HttpStatus.CREATED);
    }

    @GetMapping("/{id}")
    public ResponseEntity<User> getUserById(@PathVariable Long id) {
        User user = userService.getUserById(id);
        return new ResponseEntity<>(user, HttpStatus.OK);
    }

    @GetMapping
    public ResponseEntity<List<User>> getAllUsers() {
        List<User> users = userService.getAllUsers();
        return new ResponseEntity<>(users, HttpStatus.OK);
    }

    @PutMapping("/{id}")
    public ResponseEntity<User> updateUser(@PathVariable Long id, @RequestBody User userDetails) {
        User updatedUser = userService.updateUser(id, userDetails);
        return new ResponseEntity<>(updatedUser, HttpStatus.OK);
    }

    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
        userService.deleteUser(id);
        return new ResponseEntity<>(HttpStatus.NO_CONTENT);
    }
}

Explanation

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

Test the Application

Run the Application

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

Access the Application

  1. Open Web Browser:
    • Open a web browser and go to http://localhost:8080/api/users.
  2. Verify the Application:
    • Verify that you can perform CRUD operations on users and their associated profiles.

Conclusion

In this chapter, we built a User Management System project using Spring Boot with a one-to-one relationship between User and Profile 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-one relationships in a Spring Boot application.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top