One To One Relationship with Spring Boot + Spring Data JPA + H2 Database

In this tutorial , we will see One To One mapping of two entities using Spring Boot and Spring Data JPA using H2 database.

GitHub Link 

Tools:

  • Spring Boot
  • Spring Data JPA
  • H2 Database
  • IntelliJ IDEA
  • Maven
  • Lombok

We have two entities Student and Address. Each student has single address attached to him. And vice a versa i.e. each address is attached to student .

This is called One To One mapping between two entities. For each of this entity, table will be created in database. So there will be two tables created in database.

create table address (id bigint generated by default as identity, name varchar(255), primary key (id));
create table student (id bigint generated by default as identity, mobile integer, name varchar(255), address_id bigint, primary key (id));
alter table student add constraint FKcaf6ht0hfw93lwc13ny0sdmvo foreign key (address_id) references address(id);

Each table has primary key as ID . Two tables has One To One relationship between them. Each student has address associated with him and each address has one student.

STUDENT table has foreign key as ADDRESS_ID in it. So STUDENT is a child table and ADDRESS table is parent table in this relationship.

Now we will see how can we form this relationship using Spring data JPA entities.

Step 1: Define all the dependencies required for this project

<?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 http://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.1.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.myjavablog</groupId>
<artifactId>spring-boot-data-jpa-one-to-one</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-boot-data-jpa-one-to-one</name>
<description>Demo project for Spring Boot</description>
<pre><code><properties>
    <java.version>1.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>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <!--<scope>runtime</scope>-->
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>

    <!-- For JSP compilation -->
    <dependency>
        <groupId>org.apache.tomcat.embed</groupId>
        <artifactId>tomcat-embed-jasper</artifactId>
        <scope>provided</scope>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>
</project>

  • Lombok – We will be using lombok third party library to reduce boilerplate code for model/data objects, e.g., it can generate getters and setters for those object automatically by using Lombok annotations. The easiest way is to use the @Data annotation.
  • spring-boot-starter-data-jpa – This jar is used to connect to database .It also has a support to provide different JPA implementations to interact with the database like Hibernate, JPA Repository, CRUD Repository etc.
  • h2 – Its used to create H2 database when the spring boot application boots up. Spring boot will read the database configuration from application.properties file and creates a DataSource out of it.

Step 2: Define the Model/Entity

Student.java

package com.myjavablog.model;

import org.springframework.stereotype.Repository;

import javax.annotation.Generated;
import javax.persistence.*;
import java.util.Optional;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.*;

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "STUDENT")
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column
private String name;

@Column
private int mobile;

@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "ADDRESS_ID")
private Address address;


public Student(String name, int mobile, Address address) {
    this.name=name;
    this.mobile=mobile;
    this.address=address;
}

@Override
public String toString() {
    return "Student{" +
            "id=" + id +
            ", name='" + name + '\'' +
            ", mobile=" + mobile +                
            '}';
}
}

Address.java

package com.myjavablog.model;

import javax.persistence.*;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.*;

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name = "ADDRESS")
public class Address {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column
private String name;

@OneToOne(mappedBy = "address")
private Student student;

public Address(String name) {
    this.name =name;
}

@Override
public String toString() {
    return "Address{" +
            "id=" + id +
            ", name='" + name + '\'' +
            '}';
}
}

Below are the Annotations used while creating the entity classes –

Lombok annotations –

  • @Data – Define this class as Model class
  • @Builder – To build the model object at runtime ex. Create mock object for unit testing
  • @AllArgsConstructor – Create constructor with all arguments
  • @NoArgsConstructor – Default constructor

Spring Data JPA Annotations –

  • @Entity – This annotation marks the class annotations.
  • @Table – This annotation creates table in database.
  • @Id – It creates primary key in table.
  • @GeneratedValue – It defines primary key generation strategy like AUTO,IDENTITY,SEQUENCE etc.
  • @Column It defines column property for table.
  • @OneToOne – This annotation creates one to one relationship between Student and Address entities. The cascade property (CascadeType.ALL) defines what should happen with child table records when something happens with parent table records. On DELETE, UPDATE , INSERT operations in parent table child table should also be affected.
  • @JoinColumn – You can define column which creates foreign key in a table. In our example, ADDRESS_ID is a foreign key in STUDENT table which references to ID in ADDRESS table.

Step 3: Create the JPA repositories to query STUDENT and ADDRESS tables

StudentRepository and AddressRepository implemets JpaRepository which has methods to perform all CRUD operations. It has methods like save(), find(), delete(),exists(),count() to perform database operations.

package com.myjavablog.dao;

import com.myjavablog.model.Student;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface StudentRepository extends JpaRepository<Student, Long> {
public Student findByName(String name);
}

package com.myjavablog.dao;

import com.myjavablog.model.Address;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface AddressRepository extends JpaRepository<Address, Long>{
}

Step 4: Create the class BeanConfig to configure the bean for H2 database

This class creates a bean ServletRegistrationBean and autowires it to spring container. This bean actually required to access H2 database from console through browser.

package com.myjavablog;

import org.h2.server.web.WebServlet;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class BeanConfig {
@Bean
ServletRegistrationBean h2servletRegistration() {
    ServletRegistrationBean registrationBean = new ServletRegistrationBean(new WebServlet());
    registrationBean.addUrlMappings("/console/*");
    return registrationBean;
}
}

Step 5: Lat but not the least, You need to define application properties.

<h1>DATASOURCE (DataSourceAutoConfiguration & DataSourceProperties)</h1>
spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.username=sa
spring.datasource.password=
<h1>Hibernate</h1>
<h1>The SQL dialect makes Hibernate generate better SQL for the chosen database</h1>
spring.jpa.properties.hibernate.dialect =org.hibernate.dialect.H2Dialect
spring.datasource.driverClassName=org.h2.Driver
<h1>Hibernate ddl auto (create, create-drop, validate, update)</h1>
spring.jpa.hibernate.ddl-auto = update

logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type=TRACE
server.port=8082
server.error.whitelabel.enabled=false

Step 6: Now run the application

Once you run the application records will be inserted to tables as below –

Leave a Comment

Bitnami