Integrating Hibernate and JPA with Spring Boot

Image Image

This guide will help you create a simple project with Spring Boot and connect to a database using Hibernate/JPA. We will use Spring Boot Starter JPA and in memory database H2.

You will learn

  • Basics of JPA/Hibernate
  • How to create a project using Spring Boot, Spring Boot Starter JPA and H2?
  • How to use Spring Boot Starter JPA?
  • How to connect a Spring Boot project to database using JPA/Hibernate?
  • How to create a simple JPA Entity with a primary key?
  • How to write a simple repository interface extending JpaRepository interface?
  • What are the basics of an in memory database?

Spring Boot and Hibernate Course


Project Code Structure

Following screenshot shows the structure of the project we will create. Image

A few details:

  • - Entity bean to store student details.
  • - Extends JpaRepository. Acts as a repository to update/retrieve Student entities.
  • data.sql - We use data.sql to populate the initial student data.
  • - The main Spring Boot Application class which is used to launch up the application. We will extend CommandLineRunner interface and implement public void run(String... args) method to launch the spring jpa repository methods when the server launches up.
  • pom.xml - Contains all the dependencies needed to build this project. We will use Spring Boot Starter JPA and Web other than Developer Tools and H2 as in memory database.

Tools you will need

  • Maven 3.0+ is your build tool
  • Your favorite IDE. We use Eclipse.
  • JDK 1.8+

Complete Maven Project With Code Examples

Our Github repository has all the code examples -

Free Courses - Learn in 10 Steps

How does JPA/Hibernate Work?

Databases are designed with Tables/Relations. Java objects are designed using OOPS. We would want to store the data from objects into tables and vice-versa.

Earlier approaches involved writing SQL Queries. JDBC, Spring JDBC and myBatis were popular approaches.

However, JPA evolved as a result of a different thought process.

How about mapping the objects directly to tables/relationships?

This Mapping is also called ORM - Object Relational Mapping. Before JPA, ORM was the term more commonly used to refer to these frameworks. Thats one of the reasons, Hibernate is called a ORM framework.

Important Concepts in JPA


JPA allows to map application classes to tables in database.

  • Entity Manager - Once the mappings are defined, entity manager can manage your entities. Entity Manager handles all interactions with the database
  • JPQL (Java Persistence Query Language) - Provides ways to write queries to execute searches against entities. Important thing to understand is the these are different from SQL queries. JPQL queries already understand the mappings that are defined between entities. We can add additional conditions as needed.
  • Criteria API defines a Java based API to execute searches against databases.

JPA vs Hibernate

Hibernate is one of the most popular ORM frameworks.

JPA defines the specification. It is an API.

  • How do you define entities?
  • How do you map attributes?
  • How do you map relationships between entities?
  • Who manages the entities?

Hibernate is one of the popular implementations of JPA.

  • Hibernate understands the mappings that we add between objects and tables. It ensures that data is stored/retrieved from the database based on the mappings.
  • Hibernate also provides additional features on top of JPA. But depending on them would mean a lock in to Hibernate. You cannot move to other JPA implementations like Toplink.

Creating the Project with Spring Initializr

Spring Initializr is great tool to bootstrap your Spring Boot projects.


As shown in the image above, following steps have to be done

  • Launch Spring Initializr and choose the following
    • Choose as Group
    • Choose spring-boot-2-jpa-with-hibernate-and-h2 as Artifact
    • Choose following dependencies
      • Web
      • JPA
      • H2
      • DevTools
  • Click Generate Project.
  • Import the project into Eclipse. File -> Import -> Existing Maven Project.

Starter Projects in pom.xml

Below is the list of starter projects in pom.xml.



Image Image Image



Understanding Spring Boot Starter JPA

Below picture highlights some of the dependencies that are part of the imported JPA project. Image

Key Question : How did all these dependencies come in?

All these dependencies are defined in spring-boot-starter-jpa. As soon as we include Spring Boot Starter JPA in our project (pom.xml), we get the following features from a wide variety of dependencies

  • AOP
  • Transaction Management
  • JPA Implementation - Default Hibernate
  • JDBC

Extract below shows some code from pom.xml of spring-boot-starter-jpa.


Enable H2 Console

We will use H2 as the database.

H2 provides a web interface called H2 Console to see the data. Let’s enable h2 console in the


# Enabling H2 Console

When you reload the application, you can launch up H2 Console at http://localhost:8080/h2-console.


Tip - Make sure that you use jdbc:h2:mem:testdb as JDBC URL.

When you use the right JDBC URL given above, you should see an empty schema when you click Connect button. Image

Create Your First JPA Entity

The first step is to create a JPA Entity. Lets create a simple Student Entity with a primary key id.

package com.in28minutes.springboot.jpa.hibernate.h2.example.student;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

public class Student {
	private Long id;
	private String name;
	private String passportNumber;

	public Student() {

	public Student(Long id, String name, String passportNumber) {
		super(); = id; = name;
		this.passportNumber = passportNumber;

	public Student(String name, String passportNumber) {
		super(); = name;
		this.passportNumber = passportNumber;

	public Long getId() {
		return id;

	public void setId(Long id) { = id;

	public String getName() {
		return name;

	public void setName(String name) { = name;

	public String getPassportNumber() {
		return passportNumber;

	public void setPassportNumber(String passportNumber) {
		this.passportNumber = passportNumber;

	public String toString() {
		return String.format("Student [id=%s, name=%s, passportNumber=%s]", id, name, passportNumber);


Important things to note:

  • @Entity: Specifies that the class is an entity. This annotation is applied to the entity class.
  • @Id: Specifies the primary key of an entity.
  • @GeneratedValue: Provides for the specification of generation strategies for the values of primary keys.
  • public Student(): Default constructor to make JPA Happy

When the application reloads, you can launch H2 console at http://localhost:8080/h2-console.

You will see that a new table called ‘student’ is created in H2 Console.

How did the Student table get created?

Its because of Spring Boot Auto Configuration. We will talk about this a little later.

Let’s now populate some data into the student table.


insert into student
values(10001,'Ranga', 'E1234567');

insert into student
values(10002,'Ravi', 'A1234568');

When the application reloads you would see following statements in the log indicating that the sql files are picked up.

Executing SQL script from URL [file:/in28Minutes/git/spring-boot-examples/spring-boot-2-jdbc-with-h2/target/classes/data.sql]

After App Reload, When you login to H2 Console (http://localhost:8080/h2-console) you can see that the student table is created and the data is populated.


Create Repository class to Read Student information


We create a simple interface StudentRepository extending JpaRepository.

package com.in28minutes.springboot.jpa.hibernate.h2.example.student;

import org.springframework.stereotype.Repository;

public interface StudentRepository extends JpaRepository<Student, Long>{



  • We will talk about all the methods in the JpaRepository a little later.
  • public interface StudentRepository extends JpaRepository<Student, Long> - We are extending JpaRepository using two generics - Student & Long. Student is the entity that is being managed and the primary key of Student is Long.


JpaRepository (Defined in Spring Data JPA) is the JPA specific Repository interface.

public interface JpaRepository<T, ID extends Serializable>
		extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {

JpaRepository extends PagingAndSortingRepository which in turn extends CrudRepository interface. So, JpaRepository inherits all the methods from the two interfaces shown below.


public abstract interface PagingAndSortingRepository extends CrudRepository {
  public abstract Iterable findAll(Sort arg0);
  public abstract Page findAll(Pageable arg0);



public interface CrudRepository<T, ID extends Serializable>
    extends Repository<T, ID> {

    <S extends T> S save(S entity);

    T findOne(ID primaryKey);       

    Iterable<T> findAll();          

    Long count();                   

    void delete(T entity);          

    boolean exists(ID primaryKey);  

    // … more functionality omitted.

Enable Debug Logging for Hibernate and Queries

Before we go any further, let’s enable logging for all queries generated by Hibernate. We also enable statistics and format generated sql statements.


#Turn Statistics on
# Show all queries

Some of the log that is generated (later when we execute queries) when we turn statistics on is shown below.

Session Level Metrics

i.StatisticalLoggingSessionEventListener : Session Metrics {
    23004 nanoseconds spent acquiring 1 JDBC connections;
    0 nanoseconds spent releasing 0 JDBC connections;
    41930 nanoseconds spent preparing 1 JDBC statements;
    174065 nanoseconds spent executing 1 JDBC statements;
    0 nanoseconds spent executing 0 JDBC batches;
    0 nanoseconds spent performing 0 L2C puts;
    0 nanoseconds spent performing 0 L2C hits;
    0 nanoseconds spent performing 0 L2C misses;
    0 nanoseconds spent executing 0 flushes (flushing a total of 0 entities and 0 collections);
    5125 nanoseconds spent executing 1 partial-flushes (flushing a total of 0 entities and 0 collections)

Queries and Parameters

    select as id1_0_, as name2_0_,
        student0_.passport_number as passport3_0_ 
        student student0_
2017-12-05 10:20:59.457 TRACE 26877 --- [  restartedMain] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([id1_0_] : [BIGINT]) - [1]
2017-12-05 10:20:59.458 TRACE 26877 --- [  restartedMain] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([name2_0_] : [VARCHAR]) - [John]
2017-12-05 10:20:59.458 TRACE 26877 --- [  restartedMain] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([passport3_0_] : [VARCHAR]) - [A1234657]
2017-12-05 10:20:59.458 TRACE 26877 --- [  restartedMain] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([id1_0_] : [BIGINT]) - [10001]
2017-12-05 10:20:59.458 TRACE 26877 --- [  restartedMain] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([name2_0_] : [VARCHAR]) - [Name-Updated]
2017-12-05 10:20:59.458 TRACE 26877 --- [  restartedMain] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([passport3_0_] : [VARCHAR]) - [New-Passport]
2017-12-05 10:20:59.458 DEBUG 26877 --- [  restartedMain] o.h.s.internal.ConcurrentStatisticsImpl  : HHH000117: HQL: select generatedAlias0 from Student as generatedAlias0, time: 1ms, rows: 2

Exploring JpaRepository methods

Code belows shows the SpringBoot2JPAWithHibernateAndH2Application class extended to execute some of the StudentRepository methods.

public class SpringBoot2JPAWithHibernateAndH2Application implements CommandLineRunner {

	private Logger logger = LoggerFactory.getLogger(this.getClass());

	StudentRepository repository;

	public static void main(String[] args) {, args);

	public void run(String... args) throws Exception {
		//Code to run at application startup

Spring Boot Auto Configuration sees H2 in the classpath. It understands that we would want to talk to an in memory database. It auto configures a datasource and also a JdbcTemplate connecting to that datasource.

Important Things To Note

  • SpringBoot2JPAWithHibernateAndH2Application implements CommandLineRunner - Implementing CommandLineRunner helps to execute the repository methods at start of the application.
  • public void run(String... args) throws Exception { - Implement the run method defined in the CommandLineRunner interface. This method is executed as soon as the application is launched up.

Let’s extend the run method to execute a few methods on the student repository.

public void run(String... args) throws Exception {"Student id 10001 -> {}", repository.findById(10001L));"All users 1 -> {}", repository.findAll());
	//Insert"Inserting -> {}", Student("John", "A1234657")));

	//Update"Update 10001 -> {}", Student(10001L, "Name-Updated", "New-Passport")));

	repository.deleteById(10002L);"All users 2 -> {}", repository.findAll());

Important points to Note:

  • findById, findAll, deleteById methods are self explanatory.
  • `save’ method is used for both insertion and updates. If the entity is already present in the database, it is updated. Else, it is inserted.

Output from above statements when the code is run is shown below:

Student id 10001 -> Optional[Student [id=10001, name=Ranga, passportNumber=E1234567]]
All users 1 -> [Student [id=10001, name=Ranga, passportNumber=E1234567], Student [id=10002, name=Ravi, passportNumber=A1234568]]
Inserting -> Student [id=1, name=John, passportNumber=A1234657]
Update 10001 -> Student [id=10001, name=Name-Updated, passportNumber=New-Passport]
All users 2 -> [Student [id=1, name=John, passportNumber=A1234657], Student [id=10001, name=Name-Updated, passportNumber=New-Passport]]

Few more advanced JPA/Hibernate ORM Mappings

Lets look at a few more examples to understand how JPA can be used to map objects to tables.

Example 1 - Relationships @ManyToMany

Relationships between objects are expressed in a different way compared to relationship between tables.

Each Employee can have multiple Tasks. Each Task can be shared by multiple Employees. There is a Many to Many relationship between them. We use @ManyToMany annotation to establish the relationship.

public class Employee {
     //Some other code
	private List<Task> tasks;

public class Task {

     //Some other code

	@ManyToMany(mappedBy = "tasks")
	private List<Employee> employees;
CREATE TABLE employee 
     id            BIGINT NOT NULL, 

  CREATE TABLE employee_tasks 
     employees_id BIGINT NOT NULL, 
     tasks_id     INTEGER NOT NULL 


Example 2 - Inheritance Startegies - InheritanceType.SINGLE_TABLE

Some times multiple classes are mapped to a single table and vice-versa. In these situations, we define a inheritance strategy. In this example, we use a strategy of InheritanceType.SINGLE_TABLE.


@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "EMPLOYEE_TYPE")
public  class Employee {	
    //Other Employee Attributes

public class FullTimeEmployee extends Employee {
	protected Integer salary;

public class PartTimeEmployee extends Employee {
	protected Float hourlyWage;


CREATE TABLE employee 
     employee_type VARCHAR(31) NOT NULL, 
     id            BIGINT NOT NULL, 
     city          VARCHAR(255), 
     state         VARCHAR(255), 
     street        VARCHAR(255), 
     zip           VARCHAR(255), 

     hourly_wage   FLOAT,  --PartTimeEmployee

     salary        INTEGER, --FullTimeEmployee

     PRIMARY KEY (id) 

Complete Code Example

Github repository has all the code examples -

Best Selling Udemy Courses

Image Image Image Image Image Image Image Image Image Image

Join 450,000 Learners and 30+ Amazing Courses

350,000 Learners are learning everyday with our Best Selling Courses : Spring Boot Microservices, Spring, Spring Boot, Web Services, Hibernate, Full Stack React, Full Stack Angular, Python, Spring Interview Guide, Java Interview, Java Functional Programming, AWS, Docker, Kubernetes, PCF, AWS Fargate and Azure

Do not know where to start your learning journey? Check out our amazing learning paths:
Learning Path 01 - Spring and Spring Boot Web Applications and API Developer,
Learning Path 02 - Full Stack Developer with Spring Boot, React & Angular,
Learning Path 03 - Cloud Microservices Developer with Docker and Kubernetes,
Learning Path 04 - Learn Cloud with Spring Boot, AWS, Azure and PCF and
Learning Path 05 - Learn AWS with Microservices, Docker and Kubernetes



Related Posts

Understanding jwt token

Let us understand the json web tokens

Single sign-on workflow

Let us understand the single sign-on workflow

Oauth2.0 - Resource Owner Password Credentials grant workflow

Let us understand the Oauth2.0 Resource Owner Password Credentials grant workflow

Oauth2.0 - Implicit grant workflow

Let us understand the Oauth2.0 implicit grant workflow

Oauth2.0 - Client Credentials grant workflow

Let us understand the Oauth2.0 client credentials grant workflow

Oauth2.0 - Authorization grant workflow

Let us understand the Oauth2.0 authorization grant workflow

Writing Integration Tests for Rest Services with Spring Boot

Setting up a basic REST Service with Spring Boot is a cake walk. We will go one step further and add great integration tests!

Integrating Spring Boot and Spring JDBC with H2 and Starter JDBC

Learn using Spring Boot Starter JDBC to connect Spring Boot to H2 (in memory database) using Spring JDBC. You will create a simple project with Spring Boot. You will add code to the project to connect to a database using Spring JDBC. You will learn to implement the basic CRUD methods.

JUnit Tutorial for Beginners in 5 Steps

JUnit Tutorial for Beginners in 5 Steps. Setting up a basic JUnit example and understanding the basics of junit.

JPA and Hibernate Tutorial For Beginners - 10 Steps with Spring Boot and H2

JPA and Hibernate in 10 Steps with H2 - Setting up a basic project example with Spring Boot and in memory database H2. Its a cake walk.