One-to-One Unidirectional Mapping with MapsId

In this topic, we will learn about how to implement one-to-one unidirectional mapping with MapsId(@MapsId) annotation using Spring Boot, Hibernate, Spring Data JPA, H2 Database, and Lombok.
The @MapsId annotation is used to establish the relationship between two entities. One primary key of one table is the foreign key to another table. We have shared the primary key between the two entities.

one-to-one_unidirectional_mapping

The one-to-one unidirectional mapping with @MapsId annotation means a one-side relationship(employee table to address table). We will create a restful web service example for implementing this one-to-one unidirectional mapping with @MapsId in the spring boot step-by-step. Let’s begin to implement this

Table of contents
  1. Create a Spring Boot Starter Project(one-to-one unidirectional mapping with @MapsId) 
  2. Maven Dependency
  3. Define H2 database configuration
  4. Create Entity
  5. Create Repository
  6. Create Service
  7. Create Model
  8. Create Controller
  9. Run the Spring Boot Application
 10. Conclusion

1. Create a Spring Boot Starter Project(one-to-one unidirectional mapping with @MapsId)

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

Project Structure of Spring Boot Application

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 H2 database configuration

We are defining the H2 database configuration in the application.properties file of the application.

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

Employee.java

package com.springjava.entity;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MapsId;
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)
@MapsId
private Address address;
}

→ This @OneToOne annotation is used on the address property of the Employee entity class indicating that there is a one-to-one relation from the Employee entity to the Address entity.
→ This @MapsId annotation indicates that the primary key of the Employee entity class is used as a foreign key to the Address entity class.
→ These two annotations indicate that both the source and target entities share the common primary key values.
→ The Address entity class does not contain any reference to Employee, as this is a unidirectional relationship(from Employee to Address).

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 are using Lombok annotation to generate(constructor, setter, getter etc).

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 Integer id;
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.ArrayList;
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> respMap = new LinkedHashMap <String, Object>();
    //creating address object and setting properties
    Address address = new Address();
    address.setStreet(empModel.getStreet());
    address.setCity(empModel.getCity());
    address.setState(empModel.getState());
    Employee emp = new Employee();
    emp.setName(empModel.getName());
    emp.setEmailId(empModel.getEmailId());
    emp.setMobNo(empModel.getMobNo());
    emp.setDesign(empModel.getDesign());
    emp.setAddress(address);
    //saving employee into db
    employeeService.save(emp);
    respMap.put("status", 1);
    respMap.put("message", "Record is Saved Successfully!");
    return new ResponseEntity < > (respMap, HttpStatus.CREATED);
  }

  @GetMapping("/employees")
  public ResponseEntity < ? > getEmployees() {
    Map <String, Object> respMap = new LinkedHashMap <String, Object>();
    List <Employee> listEmp = employeeService.findAll();
    List <EmployeeModel> empRespList = new ArrayList < > ();
    if (!listEmp.isEmpty()) {
      for (Employee emp: listEmp) {
        EmployeeModel empModel = new EmployeeModel();
        empModel.setId(emp.getId());
        empModel.setName(emp.getName());
        empModel.setEmailId(emp.getEmailId());
        empModel.setMobNo(emp.getMobNo());
        empModel.setDesign(emp.getDesign());
        empModel.setStreet(emp.getAddress().getStreet());
        empModel.setCity(emp.getAddress().getCity());
        empModel.setState(emp.getAddress().getState());
       empRespList.add(empModel);
      }
      respMap.put("status", 1);
      respMap.put("data", empRespList);
      return new ResponseEntity < > (respMap, HttpStatus.OK);
    } else {
      respMap.clear();
      respMap.put("status", 0);
      respMap.put("message", "Data is not found");
      return new ResponseEntity < > (respMap, HttpStatus.NOT_FOUND);
    }
  }
}

9. Run the Spring Boot Application

To run this application one-to-one unidirectional mapping with MapsId Right-click on the DemoApplication.java then click on Run As after that select Java Application.
To test the API on the Postman

Url: http://localhost:8080/api/save

one-to-one_unidirectional_mapping

Url: http://localhost:8080/api/employees

one-to-one_unidirectional_mapping

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 with MapsId).

h2_database_console

H2 database tables:

view_h2_database_table

one-to-one_unidirectional_mapping

10. Conclusion

In this topic, we learnt about how to implement one-to-one unidirectional mapping with @MapsId annotation in spring boot, spring data jpa, lombok and h2 database with the rest API example.

Leave a Comment