JPA One To One unidirectional Mapping example
Tags: java, webdev, database, todayilearned
Published: 2022-09-07 03:48:09

In this tutorial, I will show you how to implement Spring JPA One-To-One unidirectional mapping with Hibernate in a Spring Boot example using <code>@OneToOne</code> annotation. You'll know:
<ul>
    	<li>How to configure Spring Data, JPA, Hibernate to work with Database</li>
    	<li>How to define Data Models and Repository interfaces for JPA One-To-One relationship</li>
   	<li>Way to use Spring JPA to interact with Database for One-To-One association</li>
	<li>Way to create Spring Rest Controller to process HTTP requests</li>
</ul>

Full article at: [https://www.bezkoder.com/jpa-one-to-one/](https://www.bezkoder.com/jpa-one-to-one/)

<h2><span id="Way">Appropriate way to implement JPA/Hibernate One To One mapping</span></h2>
In a relational database, a One-to-One relationship between table A and table B indicates that one row in table A links to only one row in table B, and vice versa.

For example, you need to design data model for a Tutorial Blog in which <strong>One</strong> Tutorial has corresponding Details (the Date Time it was created on, the author it was created by). So this is a One-to-One association.

You can use a Join Table (with <a href="https://docs.oracle.com/javaee/7/api/javax/persistence/JoinTable.html">@JoinTable</a> annotation). It stores the primary key values from both entities in a <strong>NEW</strong> table.

![jpa-hibernate-one-to-one-join-table](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i5cpgzjugaor2vzpbjgp.png)

Another way is to use Shared Primary Key with the Foreign Key is located in the <strong>tutorial_details</strong> table. Tutorial entity is the <em><strong>parent</strong></em>, and the Tutorial Details is the <em><strong>child</strong></em>.

![jpa-hibernate-one-to-one](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/piwujfngwtlc5b9gtvnj.png)

You can map the child entity with the parent using JPA/Hibernate <a href="https://docs.oracle.com/javaee/7/api/javax/persistence/OneToOne.html">@OneToOne</a> annotation. And in this case, only the children-side defines the relationship. We call it unidirectional One-to-One association.

Now look at the <strong>tutorial_details</strong> table that contains a Primary Key column (<code>id</code>) and a Foreign Key column (<code>tutorial_id</code>). You can see that we really need only one <strong>tutorial_details</strong> (child) row associated with a <strong>tutorial</strong> (parent) row, and the child data is hardly used in other relationships. So we can omit the child's <code>id</code> column:

![jpa-hibernate-one-to-one-example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/igetzgzk8e660om4suad.png)

<h2><span id="JPA_One_to_One">JPA One To One example</span></h2>
We're gonna create a Spring project from scratch, then we implement JPA/Hibernate One to One Unidirectional Mapping with <code>tutorials</code> and <code>tutorial_details</code> table as following:

![jpa-hibernate-one-to-one-example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/igetzgzk8e660om4suad.png)

We also write Rest Apis to perform CRUD operations on the Details entities.

These are APIs that we need to provide:
<div class="table-responsive">
<table class="table table-hover  table table-hover" width="100%">
<thead>
<tr>
<th>Methods</th>
<th>Urls</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr>
<td>POST</td>
<td>/api/tutorials/:id/details</td>
<td>create new Details for a Tutorial</td>
</tr>
<tr>
<td>GET</td>
<td>/api/details/:id</td>
<td>retrieve Details by <code>:id</code></td>
</tr>
<tr>
<td>GET</td>
<td>/api/tutorials/:id/details</td>
<td>retrieve Details of a Tutorial</td>
</tr>
<tr>
<td>PUT</td>
<td>/api/details/:id</td>
<td>update Details by <code>:id</code></td>
</tr>
<tr>
<td>PUT</td>
<td>/api/tutorials/:id/details</td>
<td>update Details of a Tutorial</td>
</tr>
<tr>
<td>DELETE</td>
<td>/api/details/:id</td>
<td>delete Details by <code>:id</code></td>
</tr>
<tr>
<td>DELETE</td>
<td>/api/tutorials/:id/details</td>
<td>delete Details of a Tutorial</td>
</tr>
<tr>
<td>DELETE</td>
<td>/api/tutorials/:id</td>
<td>delete a Tutorial (and its Details)</td>
</tr>
</tbody>
</table>
</div>

Assume that we've had <strong>tutorials</strong> table like this:

![jpa-hibernate-one-to-one-parent-table](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iodb0zyk0amkreohpnqg.png)

Here are the example requests:

- Create new Details entity: POST <code>/api/tutorials/[:id]/details</code>

![jpa-hibernate-one-to-one-create](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2r5oyg7eh7tian01h4pc.png)

<strong>tutorial_details</strong> table after that:

![jpa-hibernate-one-to-one-table](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hc5wfbug26nzbrh68985.png)

- Retrieve Details of specific Tutorial: GET <code>/api/tutorials/[:id]/details</code> or <code>/api/details/[:id]</code>

![jpa-hibernate-one-to-one-retrieve](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8z6dwcszti51kseog0xy.png)

- Update Details of specific Tutorial: PUT <code>/api/tutorials/[:id]/details</code> or <code>/api/details/[:id]</code>

![jpa-hibernate-one-to-one-update](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r3m9ej0lg1yudll1c42i.png)

- Delete Details of specific Tutorial: DELETE <code>/api/tutorials/[:id]/details</code> or <code>/api/details/[:id]</code>

![jpa-hibernate-one-to-one-delete](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6u7adg2c0esvh29vbsfs.png)

Check the <strong>tutorial_details</strong> table, row with tutorial_id=1 were deleted:

![jpa-hibernate-one-to-one-delete-db](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vj5arjjpkl7gio0zwbwi.png)

- Delete a Tutorial: DELETE <code>/api/tutorials/[:id]</code>

![jpa-hibernate-one-to-one-delete-parent](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/si5zni9mcft8zxpvkj41.png)

Tutorial (id=3) and its Details were deleted:

![jpa-hibernate-one-to-one-delete-parent-table](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n0sj6zi0lwy2ribaceyz.png)

Let's build our Spring Boot Data JPA One to One example.

<h2><span id="Spring_Boot_One_to_One">Spring Boot One to One example</span></h2>
<h3><span id="Technology">Technology</span></h3>
<ul>
    	<li>Java 8</li>
    	<li>Spring Boot 2.7.2 (with Spring Web MVC, Spring Data JPA)</li>
    	<li>H2/MySQL/PostgreSQL</li>
    	<li>Maven 3.8.1</li>
</ul>

<h3><span id="Project_Structure">Project Structure</span></h3>
![spring-data-jpa-one-to-one-unidirectional](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/modcc8gyrwka6c5u8uwi.png)

Let me explain it briefly.

– <code>Tutorial</code>, <code>TutorialDetails</code> data model class correspond to entity and table <em>tutorials</em>, <em>tutorial_details</em>.
– <code>TutorialRepository</code>, <code>TutorialDetailsRepository</code> are interfaces that extends <a href="https://docs.spring.io/spring-data/jpa/docs/current/api/org/springframework/data/jpa/repository/JpaRepository.html">JpaRepository</a> for CRUD methods and custom finder methods. It will be autowired in <code>TutorialController</code>, <code>TutorialDetailsController</code>.
– <code>TutorialController</code>, <code>TutorialDetailsController</code> are <a href="https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/bind/annotation/RestController.html">RestController</a>s which has request mapping methods for RESTful CRUD API requests.
– Configuration for Spring Datasource, JPA & Hibernate in <strong>application.properties</strong>.
– <strong>pom.xml</strong> contains dependencies for Spring Boot and MySQL/PostgreSQL/H2 database.

– About <strong>exception</strong> package, to keep this post straightforward, I won't explain it. For more details, you can read following tutorial:
<a href="https://www.bezkoder.com/spring-boot-restcontrolleradvice/">@RestControllerAdvice example in Spring Boot</a>

Step by step and Github source code can be found at:
[https://www.bezkoder.com/jpa-one-to-one/](https://www.bezkoder.com/jpa-one-to-one/)

<h2><span id="Further_Reading">Further Reading</span></h2>

Custom query with <code>@Query</code> annotation:
<a href="https://www.bezkoder.com/spring-jpa-query/">Spring JPA @Query example: Custom query in Spring Boot</a>

If you want to add Pagination to this Spring project, you can find the instruction at:
<a href="https://www.bezkoder.com/spring-boot-pagination-filter-jpa-pageable/">Spring Boot Pagination & Filter example | Spring JPA, Pageable</a>

To sort/order by multiple fields:
<a href="https://www.bezkoder.com/spring-data-sort-multiple-columns/">Spring Data JPA Sort/Order by multiple Columns | Spring Boot</a>

Handle Exception for this Rest APIs is necessary:
- <a href="https://www.bezkoder.com/spring-boot-controlleradvice-exceptionhandler/">Spring Boot @ControllerAdvice & @ExceptionHandler example</a>
- <a href="https://www.bezkoder.com/spring-boot-restcontrolleradvice/">@RestControllerAdvice example in Spring Boot</a>

Or way to write Unit Test for the JPA Repository:
<a href="https://www.bezkoder.com/spring-boot-unit-test-jpa-repo-datajpatest/">Spring Boot Unit Test for JPA Repositiory with @DataJpaTest</a>

You can also know:
- how to deploy this Spring Boot App on AWS (for free) with <a href="https://www.bezkoder.com/deploy-spring-boot-aws-eb/">this tutorial</a>.
- dockerize with <a href="https://www.bezkoder.com/docker-compose-spring-boot-mysql/">Docker Compose: Spring Boot and MySQL example</a>
- way to upload an Excel file and store the data in MySQL database with <a href="https://www.bezkoder.com/spring-boot-upload-excel-file-database/">this post</a>
- upload CSV file and store the data in MySQL with <a href="https://www.bezkoder.com/spring-boot-upload-csv-file/">this post</a>.

<ul>
	<li><a href="https://www.bezkoder.com/spring-boot-jwt-authentication/">Secure Spring Boot App with Spring Security & JWT Authentication</a></li>
	<li><a href="https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#reference">Spring Data JPA Reference Documentation</a></li>
	<li><a href="https://www.bezkoder.com/spring-boot-pagination-sorting-example/">Spring Boot Pagination and Sorting example</a></li>
</ul>

Fullstack CRUD App:
- <a href="https://www.bezkoder.com/spring-boot-vue-js-crud-example/">Vue + Spring Boot example</a>
- <a href="https://www.bezkoder.com/angular-spring-boot-crud/">Angular 8 + Spring Boot example</a>
- <a href="https://www.bezkoder.com/angular-10-spring-boot-crud/">Angular 10 + Spring Boot example</a>
- <a href="https://www.bezkoder.com/angular-11-spring-boot-crud/">Angular 11 + Spring Boot example</a>
- <a href="https://www.bezkoder.com/angular-12-spring-boot-crud/">Angular 12 + Spring Boot example</a>
- <a href="https://www.bezkoder.com/spring-boot-angular-13-crud/">Angular 13 + Spring Boot example</a>
- <a href="https://www.bezkoder.com/spring-boot-angular-14-crud/">Angular 14 + Spring Boot example</a>
- <a href="https://www.bezkoder.com/react-spring-boot-crud/">React + Spring Boot example</a>

<h2><span id="Source_Code">Source Code</span></h2>
You can find the complete source code for this tutorial on <a href="https://github.com/bezkoder/jpa-one-to-one-unidirectional">Github</a>.

One-to-Many: <a href="https://www.bezkoder.com/jpa-one-to-many/">JPA One To Many example with Hibernate and Spring Boot</a>
Many-to-Many: <a href="https://www.bezkoder.com/jpa-many-to-many/">JPA Many to Many example with Hibernate in Spring Boot</a>

You can apply this implementation in following tutorials:
- <a href="https://www.bezkoder.com/spring-boot-jpa-h2-example/">Spring JPA + H2 example</a>
- <a href="https://bezkoder.com/spring-boot-jpa-crud-rest-api/">Spring JPA + MySQL example</a>
- <a href="https://bezkoder.com/spring-boot-postgresql-example/">Spring JPA + PostgreSQL example</a>
- <a href="https://www.bezkoder.com/spring-boot-hibernate-oracle/">Spring JPA + Oracle example</a>
- <a href="https://www.bezkoder.com/spring-boot-sql-server/">Spring JPA + SQL Server example</a>

More Derived queries at:
<a href="https://www.bezkoder.com/jpa-repository-query/">JPA Repository query example in Spring Boot</a>