Last updated on March 7th, 2024
In this topic, we will learn about how to implement one-to-one unidirectional mapping with a shared primary key using Spring Boot, Hibernate, Spring Data JPA, H2 Database, and Lombok.
In one-to-one unidirectional mapping shared primary key, two tables share the same primary key.
The one-to-one unidirectional mapping means one-side navigation(employee table to address table). We will create a restful web service example for implementing this one-to-one unidirectional mapping with the shared primary key in spring boot.
Table of contents
1. Create a Spring Boot Starter Project(one-to-one unidirectional mapping with the shared primary key)
2. Maven Dependency
3. Define configuration in the application.properties
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(one-to-one unidirectional mapping with the shared primary key)
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
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.OneToOne;
import javax.persistence.PrimaryKeyJoinColumn;
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)
@PrimaryKeyJoinColumn
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 association from the Employee entity to the Address entity.
→ This CascadeType.ALL attribute is also used for Address entity cannot exist without Employee entity, with this cascade setting. Address entity will be updated/deleted on subsequent update/delete on Employee entity.
→ This @PrimaryKeyJoinColumn annotation indicates that the primary key of the Employee entity is used as a foreign key to the Address entity.
→ These two annotations indicate that the source and target entities share the same primary key values.
→ The Address entity class does not reference Employee, as it 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;
}
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;
}
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> resModel = 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);
resModel.put("status", 1);
resModel.put("message", "Record is Saved Successfully!");
return new ResponseEntity <> (resModel, HttpStatus.CREATED);
}
@GetMapping("/employees")
public ResponseEntity<?> getEmployees() {
Map<String, Object> resModel= new LinkedHashMap <String, Object>();
List < Employee > listOfEmps = employeeService.findAll();
List < EmployeeModel > empResList = new ArrayList < > ();
if (!listOfEmps.isEmpty()) {
for (Employee emp: listOfEmps){
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());
empResList.add(empModel);
}
resModel.put("status", 1);
resModel.put("data", empResList);
return new ResponseEntity < > (resModel, HttpStatus.OK);
}else{
resModel.clear();
resModel.put("status", 0);
resModel.put("message", "Data is not found");
return new ResponseEntity<>(resModel, HttpStatus.NOT_FOUND);
}
}
}
9. Run the app
To run this application one-to-one unidirectional mapping with a shared primary key 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
Url: http://localhost:8080/api/employees
To check the H2 database we can browse this URL “http://localhost:8080/h2-console” on the browser to view the tables in this database which are created by this application(one-to-one unidirectional mapping with shared primary key). Then we have to click on the Connect button to connect the database and view tables.
Employee Table:
Address Table:
10. Conclusion
In this topic, we learnt how to implement one-to-one unidirectional mapping with a shared primary key (@PrimaryKeyJoinColumn annotation)in spring boot, spring data JPA, Lombok and H2 database with rest API example.