Last Updated on 07 December 2022   |   Print Email
In this Spring Data JPA article, I’d happy to share with you some code examples of mapping one to one entity relationship in relational database, with Hibernate as the underlying ORM framework and Spring Boot as the application framework.Why One to One Entity Relationship?In relational database design, we use one-to-one association when we want to segment data that would be in a single table, into 2 separate ones, for the ease of data retrieval and processing. Consider the following example:Here, a row in the products table is linked with only one row in the product_details table, and vice versa. In this article, you’ll learn how to implement different kinds of one-to-one mapping with Spring Data JPA:
Let’s see the code examples with description below.
1. Spring Data JPA One to One with Shared Primary Key
Suppose that we need to implement the following one to one relationship between tables products and product_details:
This is called one to one with shared primary key because the both tables sharing the same values of in their primary keys, in which the product_id column of the product_details table is also a foreign key referring the id column of the products table.So in Java code, we write the Product class that maps with the products table as follows:
Note that the @OneToOne and @PrimaryKeyJoinColumn annotations are used for the field detail of type ProductDetail.And code the ProductDetail class that maps with the product_details table as follows:
Note that the field product of type Product is annotated with @OneToOne, @JoinColumn and @MapsId annotations.And to make use of Spring Data JPA, create the following repository interface:
And below is a sample unit test class that tests persisting a new Product object and listing all products:
package net.codejava;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase.Replace;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.test.annotation.Rollback;
@DataJpaTest
@AutoConfigureTestDatabase(replace = Replace.NONE)
@Rollback(false)
public class ProductRepositoryTests {
@Autowired private ProductRepository repo;
@Test
public void testListAll() {
List<Product> products = repo.findAll();
assertThat(products).isNotEmpty();
products.forEach(System.out::println);
}
@Test
public void testAdd() {
Product product = new Product("iPhone 15", 999);
ProductDetail detail = new ProductDetail();
detail.setProduct(product);
product.setDetail(detail);
detail.setDescription("New iPhone version in 2023");
detail.setWeight(2.5f);
detail.setHeight(0.7f);
detail.setLength(4.0f);
detail.setWidth(3.5f);
Product savedProduct = repo.save(product);
assertThat(savedProduct).isNotNull();
}
}
You see, the code is self-explanatory. Note that in this one-to-one with shared primary key entity relationship, a product must have details (mandatory).
2. Spring Data JPA One to One with Foreign Key
The second kind of one-to-one relationship is with foreign key on the owner side. Suppose that we need to map the following two tables with Spring Data JPA:Here, the products table has a foreign key column detail_id that refers to the primary key column id of the product_details table.To implement this kind of one to one relationship, code the Product class as below:
As you can see, there’s no reference to Product in the ProductDetail class, thus the relationship is unidirectional.To make use of Spring Data JPA, code the repository interface as usual:
For your reference, below is an example unit test class:
package net.codejava;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase.Replace;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.test.annotation.Rollback;
@DataJpaTest
@AutoConfigureTestDatabase(replace = Replace.NONE)
@Rollback(false)
public class ProductRepositoryTests {
@Autowired private ProductRepository repo;
@Test
public void testListAll() {
List<Product> products = repo.findAll();
assertThat(products).isNotEmpty();
products.forEach(System.out::println);
}
@Test
public void testAdd() {
Product product = new Product("iPhone 15", 999);
ProductDetail detail = new ProductDetail();
product.setDetail(detail);
detail.setDescription("New iPhone version in 2023");
detail.setWeight(2.5f);
detail.setHeight(0.7f);
detail.setLength(4.0f);
detail.setWidth(3.5f);
Product savedProduct = repo.save(product);
assertThat(savedProduct).isNotNull();
}
}
Also note that, it’s mandatory for a product to have details.
3. Spring Data JPA One to One with Join Table
The third kind of one-to-one entity relationship is with join table, which should be used if it’s not mandatory. Consider the following example:In this one to one relationship between products and details, a product can have details or not, so we need the join table product_details in order to avoid null values if a product doesn’t have details.In Java code, we write the Product entity class as follows:
The code is self-explanatory, and I hope you understand the purpose of using join table in one to one entity relationship. You can download the sample project code under the Attachments section below.To see the coding in action, watch my video below:
Nam Ha Minh is certified Java programmer (SCJP and SCWCD). He began programming with Java back in the days of Java 1.4 and has been passionate about it ever since. You can connect with him on Facebook and watch his Java videos on YouTube.
Comments