Object Relation Mapping with Spring Boot

Gayani Nisansala
6 min readSep 27, 2021

--

Object Relation Mapping from scratch with Spring Boot…

Spring Data JPA (Java Persistence API) is used to store and retrieve data in relational database. JPA follows the object relation mapping (ORM) and it provides interfaces that provides APIs for processing queries and transactions on database.

In this tutorial I am going to discuss about the object to relation mapping and how can we used JPA to develop object to relation mapping.

Prerequisites-

  • Knowledge of Java programming language
  • Basic knowledge about creating a Spring Boot project. For this step you can follow my previous article which is mentioned below.

Let’s consider that there is a system that every author who registered in the system need to have a profile. Let’s consider this scenario to see how this object to relation mapping needs to be happened from the below image.

Object to relation mapping of profile

In the Profile object, it has member variables such as id, profileLine, startedDate and lastUpdated. Also this object has getters and setters as well.

The relationship between the profile and author needs to be maintained. Every author has only one profile. That relationship can be managed in the following way.

Object to relation mapping of author

In the Author object, it has member variables such as id, authorName, age and profile. Also this object has getters and setters as well.

As the next step, let’s find out how the Spring JPA handles this object to relation mapping by considering above scenario.

Step 01- Creating the project using spring initializr.

For creating a project using spring initializr, you can refer the previous article by clicking here.

In the project creation, you need to add the dependencies such as Spring Data JPA, H2 Database, Spring Boot DevTools and Spring Web. “Spring Data JPA” dependency is need to persist data in SQL databases. “H2 Database” is a dependency to use h2 in-memory database. “Spring Boot DevTools” is an amazing dependency that you can use to accelerate your developments from its features like fast application restarts, live reload etc.

If you have an already created Spring Boot project, you can add the below dependencies to pom.xml file. You need to add the below snippet within the <dependencies> </dependencies> scope of pom.xml file.

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>

Step 02- Adding configurations related to in-memory database in application.properties file

spring.jpa.show-sql=true
spring.h2.console.enabled=true
spring.datasource.url=jdbc:h2:mem:testdb

Step 03- Creating Author.java, AuthorRepository.java and AuthorService.java files

Author.java class is the model class and in this class we are using JPA annotations like @Entitiy, @Id, @Table, @Column, @OneToOne etc. Code snippet for creating Author.java is as follows.

@Entity
@Table(name = "author")
public class Author {
@Id
@GeneratedValue
@Column(name = "author_id")
private Long id;
@Column(name = "author_name")
private String authorName;
@Column(name = "age")
private int age;
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "profile_id")
private Profile profile;
public Author() {
}
public Author(String authorName, int age, Profile profile) {
super();
this.authorName = authorName;
this.age = age;
this.profile = profile;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getAuthorName() {
return authorName;
}
public void setAuthorName(String authorName) {
this.authorName = authorName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Profile getProfile() {
return profile;
}
public void setProfile(Profile profile) {
this.profile = profile;
}
}

In the above code snippet, @OneToOne annotation has been used to make the relation between the Profile. @OneToOne annotation is used because one author has a one profile.

@Entity annotation is used to specify that the mentioned class is an Entity and JPA will handling the creation of a table for that entity. @Table annotation can be used to specify the table name for the table that will be created by JPA. @Column annotation can be used to specify a column name as needed.

Let’s create an interface as AuthorRepository.java and extends by JpaRepository interface. Accessing the relational database is happened through the AuthorRepository.java

@Repository annotation is being used to specify that this interface is a repository.

@Repository
public interface AuthorRepository extends JpaRepository<Author, Long>{
}

Let’s create AuthorService.java class for develop business logic of the system.

@Service
public class AuthorService {
@Autowired
private AuthorRepository authorRepository;
public List<Author> getAllAuthors() {
return this.authorRepository.findAll();
}
public Author getAuthorById(Long id) {
return this.authorRepository.findById(id).get();
}
public Author saveAuthor(Author author) {
return this.authorRepository.save(author);
}
}

Step 04- Creating Profile.java, ProfileRepository.java and ProfileService.java files

Let’s first create Profile.java model class.

@Entity
@Table(name = "profile")
public class Profile {
@Id
@GeneratedValue
@Column(name = "profile_id")
private Long id;
@Column(name = "profile_link")
private String profileLink;
@Column(name = "started_date")
private LocalDate startedDate;
@Column(name = "last_updated")
private LocalDate lastUpdated;
public Profile() {
}
public Profile(String profileLink, LocalDate startedDate, LocalDate lastUpdated) {
super();
this.profileLink = profileLink;
this.startedDate = startedDate;
this.lastUpdated = lastUpdated;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getProfileLink() {
return profileLink;
}
public void setProfileLink(String profileLink) {
this.profileLink = profileLink;
}
public LocalDate getStartedDate() {
return startedDate;
}
public void setStartedDate(LocalDate startedDate) {
this.startedDate = startedDate;
}
public LocalDate getLastUpdated() {
return lastUpdated;
}
public void setLastUpdated(LocalDate lastUpdated) {
this.lastUpdated = lastUpdated;
}
}

Then let’s create a new interface called ProfileRepository which extends JpaRepository interface to access the relational database.

@Repository
public interface ProfileRepository extends JpaRepository<Profile, Long> {
}

Business logic implementations can be found in the ProfileService.java and the code snippet of the ProfileService.java as below.

@Service
public class ProfileService {
@Autowired
private ProfileRepository profileRepository;
public List<Profile> getAllAuthors() {
return this.profileRepository.findAll();
}
public Profile getAuthorById(Long id) {
return this.profileRepository.findById(id).get();
}
}

Step 05- Testing the application

In this step, we have to create a testing class to check whether the ORM happened correctly or not. For that I have created a OneToOneTester.java class as follows.

@SpringBootApplication
public class OneToOneTester implements CommandLineRunner {
@Autowired
private AuthorService authorService;
public static void main(String[] args) {
SpringApplication.run(OneToOneTester.class, args);
}
public void run(String args[]) throws Exception { Profile profile = new Profile("https://example.author1.lk", LocalDate.parse( "1997-12-03"), LocalDate.parse( "2021-08-23")); Author author = new Author("Example Author 1", 23, profile); Author savedAuthor = authorService.saveAuthor(author); System.out.println(String.format("Saved Author: \nName: %s \nAge: %s \nProfile Link: %s\n\n",
savedAuthor.getAuthorName(), savedAuthor.getAge(), savedAuthor.getProfile().getProfileLink()));
Author authorReceived = authorService.getAuthorById(savedAuthor.getId()); System.out.println(String.format("Search Results: \nName: %s \nAge: %s \nProfile Link: %s",
authorReceived.getAuthorName(), authorReceived.getAge(), savedAuthor.getProfile().getProfileLink()));
}
}

The file structure of the project has been created as below.

File structure of the project

We can access the in-memory database using http://localhost:8080/h2-console

We can run the OneToOneTester.java class as a java application and we can observe the result.

Console output of the program is shown below.

Saved Author: 
Name: Example Author 1
Age: 23
Profile Link: https://example.author1.lk
Search Results:
Name: Example Author 1
Age: 23
Profile Link: https://example.author1.lk

Step by step to view the h2 in-memory database is shown below.

Step 01: Connecting to the h2 in-memory database
Step 02: Viewing table data of author table
Step 03: Viewing table data of profile table

Finally we have come to the end of the tutorial. now you can play with the program and able to test the foreign key constraint which is created by the JPA itself.

In this tutorial I have mainly focused on a scenario which is based on “one to one” relationship. Hope you enjoyed the content of the article.

If you have any doubt please reach out to me. Happy practicing… 👩‍💻

--

--

Gayani Nisansala

Following B.Sc.(Hons) in Information Technology at University of Moratuwa, Sri Lanka