One to One mapping in JPA with Spring Boot


In this guide, we will discuss one to one mapping in JPA with Spring Boot. Spring Boot uses the Hibernate to manage the database level operation and it implements Java Persistence API (JPA) specifications. Hibernate maps the tables into the database to the entity classes of the application.

What we’ll build

In this example, we will define the one-to-one relationship between the two entities using Spring Data JPA. To do that JPA gives:

  1. @OneToOne– Specifies a single-valued association to another entity that has a one-to-one multiplicity.
  2. @JoinColumn– Specifies a column for joining an entity association or element collection.

The one-to-one relationship between EMPLOYEE and EMPLOYEE_DETAILS tables are as following:

  1. EMPLOYEE table store only basic information an employee like id, first name, last name, email.
  2. And EMPLOYEE_DETAILS table store the rest of other information of an employee like job title, gender, salary, etc.
One to One mapping in JPA with Spring Boot

Technology Used

Find the list of all technologies used in this application.

  1. Spring Tool Suite 4
  2. JDK 8
  3. Spring Boot 2.1.6.RELEASE
  4. Spring Data 2.1.9.RELEASE
  5. MySQL Database
  6. Maven 3

Dependency Required

Dependencies used in this example. Add them to pom.xml.

pom.xml
<dependencies>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-data-jpa</artifactId>
	</dependency>
	<dependency>
		<groupId>mysql</groupId>
		<artifactId>mysql-connector-java</artifactId>
		<scope>runtime</scope>
	</dependency>
</dependencies>

Steps to be follow

These are the steps we need to follow to get an error-free application.

1. Make sure the above-mentioned dependencies are in the project classpath.

2. Database connection strings have been defined in the application.properties file.

spring.datasource.url=jdbc:mysql://localhost:3306/demo
spring.datasource.username=root
#and other credentials

3. Employee entity class mappedBy="employee" field of EmployeeDetails entity class and annotated by @OneToOne annotation.

@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "employee")
private EmployeeDetails employeeDetail;

4. Similarly, EmployeeDetails entity class declared an employee field of type Employee and joined by employee_id using annotation @JoinColumn & @OneToOne.

@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "employee_id", nullable = false, unique = true)
private Employee employee;

5. Create the Employee and EmployeeDetails object of calling its parameterized constructor.

Employee employee = new Employee("Sandeep", "Jaiswal", "[email protected]");
EmployeeDetails employeeDetail = new EmployeeDetails("Database Architect", "Information Technology", "MALE", 92000L, "London,UK");

6. Set child reference (employeeDetail) in the parent entity (employee).

employee.setEmployeeDetail(employeeDetail);

7. Set parent reference(employee) in child entity(employeeDetail).

employeeDetail.setEmployee(employee);

8. Finally, save in the database.

employeeRepository.save(employee);

application.properties

Setup the database connection strings in application.properties.

application.properties
# MySQL database connection strings
spring.datasource.url=jdbc:mysql://localhost:3306/demo
spring.datasource.username=root
spring.datasource.password=root

# JPA property settings
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL55Dialect
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.show_sql=true

Entity

Create the Employee and EmployeeDetails entity class for table EMPLOYEE and EMPLOYEE_DETAILS respectively which will be mapped by one-to-one relationship.

Employee.java
package org.websparrow.entity;

import java.io.Serializable;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;

@Entity
@Table(name = "EMPLOYEE")
public class Employee implements Serializable {

	private static final long serialVersionUID = 1L;
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long id;
	private String firstName;
	private String lastName;
	@Column(unique = true)
	private String email;
	@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "employee")
	private EmployeeDetails employeeDetail;
	// TODO: Generate Getters and Setters...

	public Employee() {	}

	public Employee(String firstName, String lastName, String email) {
		super();
		this.firstName = firstName;
		this.lastName = lastName;
		this.email = email;
	}
}
EmployeeDetails.java
package org.websparrow.entity;

import java.io.Serializable;

import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;

@Entity
@Table(name = "EMPLOYEE_DETAILS")
public class EmployeeDetails implements Serializable {

	private static final long serialVersionUID = 1L;
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long id;
	private String jobTitle;
	private String department;
	private String gender;
	private Long salary;
	private String address;
	@OneToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "employee_id", nullable = false, unique = true)
	private Employee employee;
	// TODO: Generate Getters and Setters...

	public EmployeeDetails() {	}

	public EmployeeDetails(String jobTitle, String department, String gender, Long salary, String address) {
		super();
		this.jobTitle = jobTitle;
		this.department = department;
		this.gender = gender;
		this.salary = salary;
		this.address = address;
	}
}

Repository

Create an EmployeeRepository & EmployeeDetailsRepository interface which extends CrudRepository.

EmployeeRepository.java
package org.websparrow.repository;

import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import org.websparrow.entity.Employee;

@Repository
public interface EmployeeRepository extends CrudRepository<Employee, Long> {

}
EmployeeDetailsRepository.java
package org.websparrow.repository;

import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
import org.websparrow.entity.EmployeeDetails;

@Repository
public interface EmployeeDetailsRepository extends CrudRepository<EmployeeDetails, Long> {

}

Test the application

To create the one-to-one relationship between two entities implements the CommandLineRunner interface to the Spring Boot stater class and overrides it’s run() method.

OneToOneApp.java
package org.websparrow;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.websparrow.entity.Employee;
import org.websparrow.entity.EmployeeDetails;
import org.websparrow.repository.EmployeeRepository;

@SpringBootApplication
public class OneToOneApp implements CommandLineRunner {

	@Autowired
	private EmployeeRepository employeeRepository;

	public static void main(String[] args) {
		SpringApplication.run(OneToOneApp.class, args);
	}

	@Override
	public void run(String... args) throws Exception {
		// Create a new Employee
		Employee employee = new Employee("Sandeep", "Jaiswal", "[email protected]");

		// Create Employee Detail
		EmployeeDetails employeeDetail = new EmployeeDetails("Database Architect", "Information Technology", "MALE",
				92000L, "London,UK");

		// Set child reference(employeeDetail) in parent entity(employee)
		employee.setEmployeeDetail(employeeDetail);

		// Set parent reference(employee) in child entity(employeeDetail)
		employeeDetail.setEmployee(employee);

		// Save in database
		employeeRepository.save(employee);

	}
}

Console log

Execute the above class and you will find the below log on your IDE console log.

Hibernate: create table employee (id bigint not null auto_increment, email varchar(255), first_name varchar(255), last_name varchar(255), primary key (id)) engine=InnoDB
Hibernate: create table employee_details (id bigint not null auto_increment, address varchar(255), department varchar(255), gender varchar(255), job_title varchar(255), salary bigint, employee_id bigint not null, primary key (id)) engine=InnoDB
Hibernate: alter table employee drop index UK_fopic1oh5oln2khj8eat6ino0
Hibernate: alter table employee add constraint UK_fopic1oh5oln2khj8eat6ino0 unique (email)
Hibernate: alter table employee_details drop index UK_puftcdm791a7i6e45laapk3tw
Hibernate: alter table employee_details add constraint UK_puftcdm791a7i6e45laapk3tw unique (employee_id)
Hibernate: alter table employee_details add constraint FK7pypt1qfit6hwq53tch4afkuq foreign key (employee_id) references employee (id)
Hibernate: insert into employee (email, first_name, last_name) values (?, ?, ?)
Hibernate: insert into employee_details (address, department, employee_id, gender, job_title, salary) values (?, ?, ?, ?, ?, ?)

Result

Check the database, it associated the table EMPLOYEE‘s column “id” and EMPLOYEE_DETAILS‘s column “employee_id” with one-to-one mapping.

TABLE --> EMPLOYEE

    id  email                first_name  last_name  
------  -------------------  ----------  -----------
     1  [email protected]  Sandeep     Jaiswal    

TABLE --> EMPLOYEE_DETAILS

    id  address    department             gender  job_title           salary  employee_id  
------  ---------  ---------------------  ------  ------------------  ------  -------------
     1  London,UK  Informaton Technology  MALE    Database Architect   92000              1

References

  1. Annotation Type OneToOne
  2. Annotation Type JoinColumn
  3. Interface CommandLineRunner

Similar Posts

About the Author

Atul Rai
I love sharing my experiments and ideas with everyone by writing articles on the latest technological trends. Read all published posts by Atul Rai.