springjava.com
  • Core Java
  • Spring Core
  • Spring Boot
  • Spring MVC
  • Angular
  • Spring Data JPA

Related Posts

  • One-to-One Unidirectional Mapping with MapsId One-to-One Mapping using Join Table in Spring Boot JPA One-to-One Bidirectional Mapping with Shared Primary Key One-To-One Unidirectional Mapping with Shared Primary Key One-to-One Bidirectional Mapping in Spring Boot JPA One-to-One Unidirectional Mapping in Spring Boot JPA
Spring Data JPA

One-to-One Mapping using Join Table in Spring Boot JPA

Last Updated: 20-11-2023 Springjava

This topic will teach us how to implement one-to-one(@OneToOne annotation) mapping with join table(@JoinTable annotation)using Spring Boot,  Hibernate,  Spring Data JPA, H2 Database and Lombok.

one_to_one_mapping_with_join_table
                                         
In the one-to-one relationship between Employee and Address, an employee can have address detail or not, so we need the join table emp_address in order to avoid null values if an employee doesn’t have address detail.
We will create a restful web service example to implement one-to-one mapping with a join table in Spring Boot. Let’s begin to implement this

Table of Contents
    1. Create a Spring Boot Starter Project for one-to-one mapping with a join table
    2. Maven Dependency
    3. Define the H2 database configuration 
    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 mapping with a join table

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

Project Structure

project_structure_one_to_one_mapping_with_join_table

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

We are configuring the H2 database for this example(one-to-one mapping with join table) 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

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.JoinColumn;
import javax.persistence.JoinTable;
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)
@JoinTable(name = "emp_address",
    joinColumns = {@JoinColumn(name = "emp_id", referencedColumnName = "id")},
    inverseJoinColumns = {@JoinColumn(name = "addrs_id", referencedColumnName = "id")}
)
private Address address;
}

→ We created the Employee Java Bean class and annotated it with JPA annotation to map this class into a database table.
→ We use @JoinTable to generate a third table which holds foreign key columns.
→ We use Lombok annotation(@Data) to constructor, setter, getter etc.

Address.java

package com.springjava.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
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;
@OneToOne(mappedBy = "address")
private Employee employee;
}

→ We have an employee property in the Address class and an address property in the Employee class, which means we can now navigate in both directions.

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> {

}

AddressRepository.java

package com.springjava.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import com.springjava.entity.Address;
public interface AddressRepository extends JpaRepository<Address, 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()
      }
}

AddressService.java

package com.springjava.service;
import java.util.List;
import com.springjava.entity.Address;
public interface AddressService {
List<Address> findAll();
}

AddressServiceImpl.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.Address;
import com.springjava.repository.AddressRepository;
@Service
public class AddressServiceImpl implements AddressService {
@Autowired
AddressRepository addressRepository;
public List<Address> findAll() {
return addressRepository.findAll();
    }
}

7. Create Model

We are creating the Java Bean class as a model class to take employee details for save them into the database.
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.AddressService;
import com.springjava.service.EmployeeService;
@RestController
@RequestMapping("/api")
public class EmployeeController {
    @Autowired
    AddressService addressService;
    @Autowired
    EmployeeService employeeService;
    
    @PostMapping("/save")
    public ResponseEntity<?> saveEmp(@RequestBody EmployeeModel empModel) {
        Map<String, Object> model = 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());
        //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());
        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();
        List<EmployeeModel>empMList=new ArrayList<>();
        if (!empList.isEmpty()) {
            for(Employee emp:empList) {
                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());
                empMList.add(empModel);
            }
            model.put("status", 1);
            model.put("data", empMList);
            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);
        }
    }
    
    @GetMapping("/address-list")
    public ResponseEntity<?> getAddressList() {
        Map<String, Object>model = new LinkedHashMap<String, Object>();
        List<Address> addList= addressService.findAll();
        List<EmployeeModel>empMList=new ArrayList<>();
        if (!addList.isEmpty()) {
            for(Address address:addList) {
                EmployeeModel empModel=new EmployeeModel();
                empModel.setId(address.getEmployee().getId());
                empModel.setName(address.getEmployee().getName());
                empModel.setEmailId(address.getEmployee().getEmailId());
                empModel.setMobNo(address.getEmployee().getMobNo());
                empModel.setDesign(address.getEmployee().getDesign());
                empModel.setStreet(address.getStreet());
                empModel.setCity(address.getCity());
                empModel.setState(address.getState());
                empMList.add(empModel);
            }
            model.put("status", 1);
            model.put("data", empMList);
            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 run this application one-to-one mapping with Join Table 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

testing_post_mapping_api_postman

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

testing_get_mapping_api_postman

Url: http://localhost:8080/api/address-list

testing_get_mapping_api_postman

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.

h2_database_console

See all tables below here:

view_h2_database_table

view_h2_database_table

view_h2_database_table

10. Conclusion

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

One-to-One Bidirectional Mapping in Spring Boot JPA One-To-One Unidirectional Mapping with Shared Primary Key One-to-One Bidirectional Mapping with Shared Primary Key

Leave your thought here

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

springjava_com
  • © 2021 Spring Java. All Rights Reserved.
Learn
    • Core Java
    • Spring Core
    • Spring Boot
    • Spring MVC
    • Angular
    • Spring Data JPA
Quick links
  • About Us
  • Contact Us
  • Privacy Policy
Social Link
springjava.com
  • Core Java
  • Spring Core
  • Spring Boot
  • Spring MVC
  • Angular
  • Spring Data JPA
  • About Us
  • Contact Us