Spring Data JPA, Hibernate, ORM & Repository (Part 4)

Ragunath Rajasekaran
9 min readOct 1, 2019

--

This tutorial explains more about Spring Data JPA, ORM tools used to interact with Databases in Spring applications and how inversion of control helps in Spring.

Photo by Denys Nevozhai on Unsplash

Recap about my previous post

This post is a continuation of my previous post.

As part of this tutorial, we will learn about

  • What is Java Persistence API (JPA)
  • How hibernate ORM is being used to configure Entities in Java
  • Get to know about CrudRepository and its default operations(methods) and how to take advantage of it.
  • Span MySql database in local machine using Docker

What is JPA?

JPA is a specification which means a set of guidelines to be followed to represent Java objects in databases. The JPA provides a set of concepts in the form of interfaces & annotations to configure Java objects. As a result, Java object mapped as relational database tables. Relationship between Java objects would be established by adding relational annotations (one-to-many, many-to-many, one-to-one, many-to-one). If JPA is a specification, who is providing implementation? ORM tools are providing implementation for JPA. Hibernate, EclipseLink or other JAVA ORM tools are providing an ORM implementation.

In Reality, we can use ORM tools without the JPA specification. Then what is need of JPA? — For Example, EclipseLink is being used as an ORM tool for one of the project. EclipseLink has its own set of methods, configuration, annotations, etc. to map objects with relational database. In the middle of project execution, If there is a need to switch to a different ORM tool, say Hibernate, then we have to learn Hibernate way of doing configurations which in turn end up with code refactoring. This is one of the reasons for JPA existence. It abstracts common patterns and define specifications so that ORM vendors such as Hibernate, EclipseLink or others will make use of it to provide their own concrete solutions. From the developer's point of view, JPA is somewhere between ORM and the application layer and the abstract ORM responsibilities.

Configure Spring for JPA

Add required dependencies

Let’s check out the source code from my post in github(Checkout ‘data-jpa-begin’ branch)

Add the following dependencies into gradle.build

build.gradle file

Refresh dependencies and run the app and check.

build error while running SpringBoot app without datasource and url

Errors. If we watch closely, url is not defined and the datasource is not configured. These errors are all because of the newly added dependencies. Data JPA dependency is expecting us to configure datasource and URL. We need a datasource info to use in the Spring. Let’s span a MySql database in local machine using Docker container.

Setup MySql database on local machine

Here, we can find how to span MySql container locally (Local machine) using docker commands. Docker-compose is being used to configure mysql container. If would like to know more about Docker, please check out the official website.

Install Docker & docker compose and execute in terminal.

docker-compose --version

Create a docker-compose.yml file in root directory and add the following configurations

Run ‘docker-compose up’ and it will span mysql database on localhost(127.0.0.1).

docker-compose up
  • URL: jdbc:mysql://127.0.01:3306/em-dev
  • Host: 127.0.01
  • User: dev
  • Password: password
  • Database: em-dev
  • Port: 3306

Open new tab in terminal and issue the following command to know about my-sql container

docker ps

Next time we can start the docker container using container Id

docker start 0ee6ddeba0ca

Connect to DB

You can use any database tool to connect/check the database schema. I have used the IntelliJ Database tool to connect.

Connect to my-sql DB within IntelliJ

Datasource configuration

We have a database and configure the url, username & password in application.properties

Let’s run and check the results.

error message while running SpringBoot without my-sql database dependency

Why? Because we haven’t added MySql Jdbc driver as a dependency. Let’s add it in build.gradle

Let’s run and check

Successful SpringBoot run after adding my-sql dependency

See the log. Hibernate core started using MySql connecter to establish a connection with MySql server.

Let’s map Model to Database Table: JPA Specification

Model class is a very important entity to apply configurations, such as, table name, property type and constraints, relationships & etc., which in turn will be mapped to Databases. For Example, Account model will be mapped to the Accounts table in Database just by adding a few annotations on it.

  • Entity: Adding it on Model it will be treated as Entity.
  • Table: Model will be mapped to database table
  • Id: Specifies the primary key of an entity
  • GenerateValue: It has four strategies to generate Id Value. We have to choose any one of the given value or we can add custom strategy.

Constraints: Javax.validation package has constraints to be applied on attribute/field level.

Let’s add JPA specification to Account model.

Here, we have configured Account model to be mapped to the accounts table with a primary key constraint along with two more attributes.

Add SQL Configure logging into the application.properties for proper logging

We are using ddl-auto as an update — Changes which we do in Java code would reflect in the database. For Ex, We have annotated Account model as table and added three attributes. During the execution of the application, the Java annotations will ensure that the Account table will be created with the appropriate columns as well as its constraints.

Let’s run and see the results.

SpringBoot ddl-auto execution log

A new table (accounts) got created with the constraints which have configured in Account model class. Now our Account Entity changes propagated to the accounts table in MySql database.

Repository

Repository.java class
  • Indicates that an annotated class is a Repository. It is a special version of Component annotation.

If a class is being annotated with Component, then, it will be scanned by Spring and it will be available on Spring Container.

AccountRespository extends JPARepository extends PagingAndSortingRepository extends CrudRepository. What does this mean.

  • CRUD operations of Account model have been configured by Spring
  • Retrieval operations are Pageable
  • Retrieval operations are Sortable

We extend JPARepository interfaces for Database operations, but actual implementations can be taken care by Spring.

Let’s use Repositories on Controllers (IOC & DI)

  • AccountRestController declared accountRepository attribute as AccountRepository (‘private AccountRepository accountRepository;’) type.
  • Configured the constructor as AutoWired: Autowire is being used for automatic configuration in Spring. This annotation search for AccountRepository interface’s implementation of Spring Container.
  • Repository annotation: Spring provides an implementation using ‘SimpleJpaRepository’ class for AccountRepository interface and it is available in the Spring Container (Because of Component Annotation).

Let’s evaluate it by setting breakpoint in AccountController constructor.

AccountRepository debug in IntelliJ
Simple JPA Repo methods
  • Injection: Instance of SimpleJpaRepository (AccountRepository implementation) will be assigned to AccountRestController’s accountRepository (Of type AccountRepository) attribute while constructing AccountRestController class.

The above process is one of core functionality of Spring and It is called as Inversion Of Control(IOC) by Dependency Injection(DI)

As per Spring Doc the IOC definition is

IoC is also known as dependency injection (DI). It is a process whereby objects define their dependencies, that is, the other objects they work with, only through constructor arguments, arguments to a factory method, or properties that are set on the object instance after it is constructed or returned from a factory method. The container then injects those dependencies when it creates the bean. This process is fundamentally the inverse, hence the name Inversion of Control (IoC), of the bean itself controlling the instantiation or location of its dependencies by using direct construction of classes, or a mechanism such as the Service Locator pattern

Now, we have an interface and an implementation for CRUD operations, Let’s code for controller which in turn will invoke repository to make necessary changes in the database.

Controller Endpoints

Insert operation — Post (/accounts)

Let’s post an account using POST. We have invoked save method of repository to do so.

Let’s build and run in PostMan

Account API POST request in POSTMAN

And Check Database for newly created accounts.

Database check for accounts table

New Account is being created and Id is being returned along with account info.

Let us see what happens when the postman invokes /accounts POST endpoint

  • Postman calls /accounts POST endpoint
  • AccountController’s createAccount method got invoked
  • AccountController instantiates AccountRepository through constructor injection
  • addAccount method invokes AccountRepository’s save method
  • AccountRepository persists the into DB and returns updated information
  • AccountController returns what it gets from AccountRepository
  • Postman shows the response

Let us add few more accounts either by running the following SQL, or by manually calling accounts POST endpoint

Adding Data to Accounts Table

Retrieve operation — GET (/accounts & /accounts/{account-id})

Let us refactor accounts() & accountById() methods. Pageable is an interface and it provides attributes to get responses based on paging. The return value is encapsulated with Page. Using the Pageable attributes passed as a request parameter on each service would return the values appropriately.

For ex, page size is 3, sort account id in descending order & need a second page then the request would be ‘/accounts?page=0&size=3&sort=id,DESC’

  • Pageable paginate request parameters
  • return this method returns paginated accounts

Let us run and hit the service without any pagination parameters, then it would take default values and return the responses accordingly.

accounts API response without pageable using POSTMAN
SpringBoot log for accounts API without pageable parameter in the request
accounts API response with pageable using POSTMAN
SpringBoot log for accounts API with pageable parameter in the request

Update operation — PUT (/accounts/{account-id})

Let us create a method updateAccount and do the following

  • PutMapping (“/accounts/{accountId}”) Make this method get invoked while updating accounts
  • PathVariable extracts accountId from url
  • Valid validates request body
  • RequestBody passes the request as input parameter
  • return this method returns updated account information

findById returns Optional which means it returns either an Account or No Value.

  • If No Value then we are returning a 404 HTTP status
  • If the Account info is available, then we are merging the account retrieved from DB (accountFound) with a request body (account). The mergeAccount method of the Account model will merge it

Let us run!!!

accounts PUT API invocation in POSTMAN

Delete operation — DELETE (/accounts/{account-id})

Let us create a method deleteAccount and do the following

  • DeleteMapping(“/accounts/{accountId}”) Make this method get invoked while deleting accounts
  • PathVariable extracts accountId from url
  • return: this method returns success after deleting

We have achieved our goal of creating restful services for accounts to be managed in a database using SpringBoot.

Final code can be found on github at ‘data-jpa-end’ branch.

Please check out this blog to know about how we can configure Docker along with VSCode Remote Container to provide a sophisticated SpringBoot development environment

In my previous blog, we can explore why we need VSCode Remote Container and how a developer can leverage it to make their lives easier

Ragunath Rajasekaran has experience in developing full-stack applications using SpringBoot, Node, React and GraphQl technologies. He is also the AWS & Azure cloud specialist who uses the infrastructure as code (IAC) via Terraform. He worked with Spark & Hive Big Data technologies. He debuted his career as an iOS developer.
Let’s connect to
Ragunath Rajasekaran through LinkedIn, GitHub, Dev.to, Medium Email Subscription

--

--

Ragunath Rajasekaran

Sr. Tech Lead | Spring Boot | Big Data | AWS | Terraform | Spark | React | Docker