One-to-One Unidirectional Mapping in Spring Boot JPA

Last updated on April 2nd, 2024

one-to-one mapping in which one entity’s value is associated with another entity’s value. An instance of the source entity is associated with an instance of the target entity. For example, if an employee has one address, an address is associated with the employee.
This topic will teach us how to implement one-to-one unidirectional mapping using Spring Boot, Hibernate, and Spring Data JPA.

one-to-one_unidirectional_mapping

In this example, an employee table is associated with the address table with the help of a foreign key addrs_id which references the address.id. The target table(address) does not have an association with the employee table.
We will create a restful web service to implement one-to-one unidirectional mapping using Spring Boot.
Table of content
    1. Create a Spring Boot Starter Project 
    2. Maven Dependency
    3. Define configuration in the application.properties file
    4. Create Entity
    5. Create Repository
    6. Create Service
    7. Create Model
    8. Create Controller
    9. Run the app
   10. Conclusion

1. Create a Spring Boot Starter Project for One-To-One Unidirectional Mapping

Add the following dependencies: 
  • Spring Web 
  • Lombok
  • H2 Database
  • Spring Data JPA

2. Maven Dependency

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.6.3</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.springjava</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>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>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
   </build>
</project>

3. Define configuration in the application.properties file

spring.datasource.url=jdbc:h2:mem:test
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
spring.jpa.hibernate.ddl-auto=update
spring.h2.console.enabled=true

4. Create Entity

Address.java

package com.springjava.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import lombok.Data;

@Entity
@Data
public class Address {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String street;
private String city;
private String state;
}

→ We used Lombok to generate the setter and getter methods of the Address class.

Employee.java

package com.springjava.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import lombok.Data;

@Entity
@Data
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
private String emailId;
private String mobNo;
private String design;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "addrs_id", referencedColumnName = "id")
private Address address;    
}

→ This @JoinColumn annotation is applied on the owning side of the table association to define the foreign key column name and other attributes which are related to the join column. 
→ We used Lombok to generate the setter and getter methods of the Employee class.
→ This CascadeType.ALL is a cascading type in Hibernate that defines that all state transitions (create, update, delete, and refresh) should be cascaded from the parent entity to the child entities.

5. Create Repository

EmployeeRepository.java

package com.springjava.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import com.springjava.entity.Employee;
public interface EmployeeRepository extends JpaRepository<Employee, Integer> {

}

6. Create Service

EmployeeService.java

package com.springjava.service;
import java.util.List;
import com.springjava.entity.Employee;
public interface EmployeeService {
void save(Employee emp);
List<Employee> findAll();
}

EmployeeServiceImpl.java

package com.springjava.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.springjava.entity.Employee;
import com.springjava.repository.EmployeeRepository;
@Service
public class EmployeeServiceImpl implements EmployeeService {
@Autowired
EmployeeRepository employeeRepository;
@Override
public void save(Employee emp) {
employeeRepository.save(emp);    
}
@Override
public List<Employee> findAll() {
return employeeRepository.findAll()
      }
}

7. Create Model

EmployeeModel.java

package com.springjava.model;
import lombok.Data;
@Data
public class EmployeeModel {
private String name;
private String emailId;
private String mobNo;
private String design;
private String street;
private String city;
private String state;
}

8. Create Controller

EmployeeController.java

package com.springjava.controller;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.springjava.entity.Address;
import com.springjava.entity.Employee;
import com.springjava.model.EmployeeModel;
import com.springjava.service.EmployeeService;

@RestController
@RequestMapping("/api")
public class EmployeeController {
  @Autowired
  EmployeeService employeeService;

  @PostMapping("/save")
  public ResponseEntity <?> saveEmp(@RequestBody EmployeeModel empModel) {
    Map <String, Object> model = new LinkedHashMap < String, Object > ();
    //creating employee object and setting properties
    Employee emp = new Employee();
    emp.setName(empModel.getName());
    emp.setEmailId(empModel.getEmailId());
    emp.setMobNo(empModel.getMobNo());
    emp.setDesign(empModel.getDesign());
    //creating address object and setting properties
    Address address = new Address();
    address.setStreet(empModel.getStreet());
    address.setCity(empModel.getCity());
    address.setState(empModel.getState());
    emp.setAddress(address);
    //saving employee into db
    employeeService.save(emp);
    model.put("status", 1);
    model.put("message", "Record is Saved Successfully!");
    return new ResponseEntity < > (model, HttpStatus.CREATED);
  }

  @GetMapping("/employees")
  public ResponseEntity <?> getEmployees() {
    Map <String, Object> model = new LinkedHashMap <String, Object>();
    List <Employee> empList = employeeService.findAll();
    if (!empList.isEmpty()) {
      model.put("status", 1);
      model.put("data", empList);
      return new ResponseEntity < > (model, HttpStatus.OK);
    } else {
      model.clear();
      model.put("status", 0);
      model.put("message", "Data is not found");
      return new ResponseEntity < >(model, HttpStatus.NOT_FOUND);
    }
  }
}

9. Run the app

To this application, Right-click on the DemoApplication.java then click on Run As after that select Java Application.
To test the API on the Postman
API: http://localhost:8080/api/save

one_to_one_unidirectional_mapping_in_spring_boot_jpa

API: http://localhost:8080/api/employees

one_to_one_unidirectional_mapping_in_spring_boot_jpa

To check the H2 database we can browse this URL “http://localhost:8080/h2-console” on the browser to view the tables in the database which are created by this application.
 

one_to_one_unidirectional_mapping_in_spring_boot_jpa

10. Conclusion

In this topic, we learnt how to implement one-to-one unidirectional mapping using spring boot, spring data JPA, Lombok and h2 database with rest API example.

Leave a Comment