avatarVinotech

Summary

The provided content outlines the implementation of a one-to-one mapping between two entities using Spring Boot JPA with MySQL, detailing the steps and best practices for managing such relationships.

Abstract

The article "One To One mapping in Spring Boot JPA" explains the concept of a one-to-one relationship in the context of a Spring Boot application using JPA (Java Persistence API) with a MySQL database. It describes when to use a one-to-one relationship, such as when a User has exactly one Profile. The tutorial includes steps for setting up the MySQL database, configuring the Spring Boot project with necessary dependencies, defining the entities with JPA annotations like @OneToOne, @JoinColumn, and mappedBy, creating repositories for data access, implementing service layers for business logic, and building RESTful controllers for API endpoints. It also provides examples of JSON payloads for testing the API and demonstrates the resulting data structure in the MySQL database, emphasizing the importance of proper relationship management for maintaining data integrity.

Opinions

  • The author suggests that one-to-one relationships are beneficial for splitting larger tables into smaller, more efficient ones, especially when dealing with frequently and infrequently accessed data.
  • The use of @JoinColumn is recommended for explicitly defining the foreign key column, enhancing code readability and ensuring correct database schema generation.
  • The mappedBy attribute is emphasized as crucial for defining the inverse side of a bidirectional relationship, clarifying the ownership of the relationship and avoiding redundant database columns.
  • The article advocates for the importance of understanding the owner and inverse sides of a relationship in JPA to properly manage the association in the database.
  • The author encourages readers to engage with the content by testing the API using tools like Postman and suggests sharing the article with peers if found useful.

One To One mapping in Spring Boot JPA

One-to-One mapping is a type of relationship between two entities where each record in one table is associated with exactly one record in another table. This is typically used when you have two entities that have a direct correspondence with each other.

When to Use a One-to-One Relationship

A one-to-one relationship is used when one entity is associated with exactly one instance of another entity. For example, a User can have one and only one Profile. You use a one-to-one relationship when:

  • Each row in one table is associated with exactly one row in another table.
  • You want to split a larger table into smaller tables for design efficiency, especially if one part of the data is accessed frequently and the other part infrequently.
  • You want to handle optional or conditional data that only applies to some rows in another table.

Example: User-Profile One-to-One Relationship in Spring Boot with MySQL

Step 1: MySQL Database Setup Assume you have a MySQL database named userdb. You can create it using the following command:

CREATE DATABASE userdb;

Step 2: Spring Boot Project Setup

Dependencies

Add the following dependencies in your pom.xml:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

Application Properties

In your src/main/resources/application.properties, configure the MySQL database connection:

spring.datasource.url=jdbc:mysql://localhost:3306/userdb
spring.datasource.username=root
spring.datasource.password=rootpassword
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true

Step 3: Create Entities

User Entity

package com.example.demo.model;

import javax.persistence.*;

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

    private String name;

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "profile_id", referencedColumnName = "id")
    private Profile profile;

    // Getters and Setters
}

@JoinColumn

The @JoinColumn annotation specifies the foreign key column in the database that will be used to establish the relationship between the two entities.

  • name = "profile_id": This defines the name of the foreign key column in the user table. It creates a column named profile_id in the user table, which will store the primary key (id) of the profile table.
  • Without @JoinColumn, JPA would automatically generate the default column name (which might be profile_id, but explicitly defining it makes the code more readable and ensures correctness).

referencedColumnName

The referencedColumnName attribute is used to define which column in the target entity (in this case, Profile) will be used as the foreign key reference.

referencedColumnName = "id": This specifies that the profile_id in the user table references the id column in the profile table. In other words, the profile_id in the user table holds the value of the id from the profile table.

Profile Entity

package com.example.demo.model;

import javax.persistence.*;

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

    private String phoneNumber;
    private String address;

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

    // Getters and Setters
}

The mappedBy attribute in JPA is used to specify the owner side of the relationship in bidirectional associations, and it indicates which entity is responsible for managing the relationship.

Here, the Profile entity uses mappedBy to indicate that the User entity is the owner of the relationship, and Profile is the inverse side.

Explanation of mappedBy

  1. mappedBy = "profile":
  • This tells JPA that the Profile entity does not own the relationship.
  • The mappedBy attribute points to the field profile in the User entity, which means that the User entity owns the relationship and contains the foreign key (profile_id).

2. Owner vs. Inverse Side:

  • The side of the relationship that does not have mappedBy is the owner of the relationship. In this case, the User entity is the owner because it has the foreign key (profile_id) and uses @JoinColumn.
  • The side with mappedBy is the inverse side, which refers back to the owner and does not have control over the relationship (i.e., Profile just references User, but it doesn’t manage the foreign key).

Why Use mappedBy?

When defining bidirectional relationships in JPA, it’s important to specify which entity is responsible for managing the association. The mappedBy attribute is used on the inverse side to point to the owner side, which contains the foreign key and is responsible for updating and maintaining the relationship in the database.

Step 4: Create Repositories

UserRepository

package com.example.demo.repository;

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

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

ProfileRepository

package com.example.demo.repository;

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

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

Step 5: Create Service

UserService

package com.example.demo.service;

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

@Service
public class UserService {
    
    @Autowired
    private UserRepository userRepository;

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

    public User getUserById(Long id) {
        return userRepository.findById(id).orElse(null);
    }
}

Step 6: Create Controller

UserController

package com.example.demo.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.example.demo.model.User;
import com.example.demo.service.UserService;

@RestController
@RequestMapping("/users")
public class UserController {

    @Autowired
    private UserService userService;

    @PostMapping
    public User createUser(@RequestBody User user) {
        return userService.saveUser(user);
    }

    @GetMapping("/{id}")
    public User getUser(@PathVariable Long id) {
        return userService.getUserById(id);
    }
}

Step 7: Testing with Sample Input

You can use Postman or any REST client to test the API.

1. Create User with Profile:

  • Endpoint: POST /users
  • Request Body:
{
  "name": "John Doe",
  "profile": {
    "phoneNumber": "123456789",
    "address": "123 Main St"
  }
}

Response:

{
  "id": 1,
  "name": "John Doe",
  "profile": {
    "id": 1,
    "phoneNumber": "123456789",
    "address": "123 Main St"
  }
}

2. Get User by ID:

  • Endpoint: GET /users/1
  • Response:
{
  "id": 1,
  "name": "John Doe",
  "profile": {
    "id": 1,
    "phoneNumber": "123456789",
    "address": "123 Main St"
  }
}

Step 8: Output in MySQL

After creating a user, the data is stored in the MySQL database in two tables: user and profile.

In this example, the one-to-one relationship ensures that each User has exactly one Profile, and each Profile is associated with one User. This design is useful when a User's profile data is logically separated but still tightly coupled.

In This Example:

  • In the User entity, the @JoinColumn annotation on the profile field defines the foreign key (profile_id), making User the owner of the one-to-one relationship.
  • In the Profile entity, the mappedBy = "profile" points back to the User entity and indicates that Profile does not own the relationship; it is the inverse side.

👏 If you found my articles useful, please consider giving it claps and sharing it with your friends and colleagues.

To read other topics

One To One Relationship
Spring Data Jpa
Spring Jpa
Jpa
One To One
Recommended from ReadMedium