๐Ÿš€ Mastering Spring Data JPA: Implementing @OneToOne Mapping with User and AadharCard Entities ๐Ÿš€

๐Ÿš€ Mastering Spring Data JPA: Implementing @OneToOne Mapping with User and AadharCard Entities ๐Ÿš€

๐Ÿ“š A Step-by-Step Guide to Efficiently Managing Entity Relationships in Spring Boot Applications ๐Ÿ“š

ยท

5 min read

Overview

In this guide, we'll walk through how to establish a @OneToOne relationship between User and AadharCard entities. This mapping type is perfect for scenarios where one entity is closely associated with another, such as a user having a unique identification card. By the end of this tutorial, you'll clearly understand how to implement and utilize @OneToOne mappings in your Spring Boot applications.

JPA One-to-One Mapping

In JPA (Java Persistence API), a one-to-one mapping is used to define a relationship between two entities where each instance of one entity is associated with exactly one instance of the other entity. This is typically represented in the database schema with a foreign key in one table that references the primary key of another table. There are two types of one-to-one mappings: Unidirectional and Bidirectional.

Unidirectional One-to-One Mapping

In unidirectional one-to-one mapping, only one entity knows about the relationship. For example, in our User and AadharCard scenario, if the User knows about AadharCard but AadharCard does not have a reference to the User, it is unidirectional mapping.

Prerequisites

Before we dive in, ensure you have the following installed:

  • Java Development Kit (JDK) 8 or higher

  • Spring Boot

  • Spring Data JPA

  • MySQL or any other relational database

Step-by-Step Implementation

1. Setting Up the Project

Create a new Spring Boot project using Spring Initializr or your preferred IDE. Add the necessary dependencies for Spring Data JPA and MySQL connector.

  1. Spring Web

  2. Spring Data JPA

  3. MySQL Driver

  4. Lombok

2. Create Entities for Users and AadharCard

User.java

package com.Spring_Data_Jpa.Entity;

import jakarta.persistence.*;
import lombok.Data;

@Entity
@Data
@Table(name = "user")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long ID;
    private String name;
    private String email;

    @OneToOne(cascade = CascadeType.ALL)
    private AadharCard aadharCard;
}

AadharCard.java

package com.Spring_Data_Jpa.Entity;

import jakarta.persistence.*;
import lombok.Data;

@Entity
@Data
@Table(name = "aadhar")
public class AadharCard {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private long ID;
    private long number;
}

3. Repository interface for managing entities

UserRepository

package com.Spring_Data_Jpa.Repository;

import com.Spring_Data_Jpa.Entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

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

AadharCardRepository

package com.Spring_Data_Jpa.Repository;

import com.Spring_Data_Jpa.Entity.AadharCard;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface AadharCardRepository extends JpaRepository<AadharCard, Long> { }

UserController

package com.Spring_Data_Jpa.Controller;

import com.Spring_Data_Jpa.Entity.User;
import com.Spring_Data_Jpa.Repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    @Autowired
    UserRepository userRepository;

    @PostMapping("/addUser")
    public String addUser(@RequestBody User user) {

        userRepository.save(user);
        return "User and AadharCard saved successfully!";
    }
}

5. Database Configuration

spring.application.name=Spring-Data-JPA

#Database MySQL
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3307/mapping_db
spring.datasource.username=root
spring.datasource.password=root1234
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect

6. SQL Scripts

use user_db;

CREATE TABLE aadhar (
  id bigint NOT NULL AUTO_INCREMENT,
  number bigint NOT NULL unique,
  PRIMARY KEY (id)
);

CREATE TABLE user (
  ID bigint NOT NULL AUTO_INCREMENT,
  name varchar(100) DEFAULT NULL,
  email varchar(100) DEFAULT NULL,
  aadhar_card_id bigint DEFAULT NULL,
  PRIMARY KEY (ID),
  UNIQUE KEY (aadhar_card_id),
  CONSTRAINT FOREIGN KEY (aadhar_card_id) REFERENCES aadhar (id)
);

Testing the @OneToOne Mapping with Postman

Add User: POST /addUser

{
    "name" : "K Jordan",
    "email" : "jordank@gmail.com",
     "aadharCard": {
        "number": 516273819025
    }
}

In the unidirectional mapping, each User has a field called aadhar_card_id, which acts as a foreign key referencing the AadharCard entity. This setup allows us to associate each User with exactly one AadharCard, and the relationship is established by storing the AadharCard ID in the User table.

Bidirectional One-to-One Mapping

In bidirectional one-to-one mapping, both entities are aware of the relationship. Continuing with our example, if the User has a reference to AadharCard and AadharCard also has a reference to the User, it is bidirectional mapping.

You need to add a@OneToOneannotation in theAadharCardentity to reference theUserentity. Additionally, you need to update theUserthe entity to properly link to theAadharCardentity. Here's how you can do it:

AadharCard

package com.Spring_Data_Jpa.Entity;

import jakarta.persistence.*;
import lombok.Data;

@Entity
@Data
@Table(name = "aadhar")
public class AadharCard {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private long ID;

    @Column(name = "number")
    private long number;

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "user_id")
    private User user;
}

UserController

In the controller, ensure that you set both sides of the relationship before saving:

package com.Spring_Data_Jpa.Controller;

import com.Spring_Data_Jpa.Entity.AadharCard;
import com.Spring_Data_Jpa.Entity.User;
import com.Spring_Data_Jpa.Repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    @Autowired
    UserRepository userRepository;

    @PostMapping("/addUser")
    public String addUser(@RequestBody User user, AadharCard aadharCard) {

        // Ensure both sides of the relationship are properly set
        if (user.getAadharCard() != null) {
            aadharCard = user.getAadharCard();
            aadharCard.setUser(user); // Set the user in the AadharCard
        }
        userRepository.save(user);
        return "User and AadharCard saved successfully!";
    }
}

In the bidirectional mapping, each User the entity has a field called aadharCard that holds a reference to its associated AadharCard entity, and each AadharCard the entity has a field called user that holds a reference back to its associated User entity. This bidirectional relationship enables us to navigate from a User to its AadharCard and vice versa, providing more flexibility in managing and accessing the relationship between the two entities.

Conclusion:

In our setup, we've implemented both unidirectional and bidirectional one-to-one mappings between the User and AadharCard entities.

These mappings provide us with flexibility in managing the relationship between users and AadharCards. The unidirectional mapping simplifies the database structure by storing the AadharCard ID in the User table, while the bidirectional mapping allows for easy navigation between User and AadharCard entities, enhancing the readability and maintainability of our code.

GitHub Access:

You can access the code on GitHub here. Feel free to fork the repository and try it out yourself.

About Me:

LinkedIn | GitHub

ย