Blog post

A beginner’s guide to using SpringData JPA with Hibernate in Spring Boot.

Aditya Shedge

-
September 22, 2025
Spring Boot
Java
Hibernate Jpa

In this guide, we’ll be using Spring Data JPA to interact with the database in a Spring Boot application. Spring Data JPA is a layer on top of the Java Persistence API (JPA) that makes it easier to work with ORM in Spring projects.

Under the hood, it uses Hibernate as the default JPA provider, which means you get all of Hibernate’s ORM features without writing its APIs directly.

Hibernate provides a very powerful object relational mapper (ORM) which is used to map your POJO classes as entities in your relational database.

Instead of writing SQL queries manually for every CRUD operation, Hibernate lets you work with objects, and it handles the underlying database interactions for you.

Now how do we use Hibernate in our Spring Boot project..

Here are the steps you can follow -

Some pre-requisites you will need are:

  • JDK 17+ installed
  • IDE (IntelliJ, VS Code, etc.)
  • PostgreSQL or MySQL running locally or in Docker. (or use H2 for quick testing)

To use Hibernate, there is no additional installation required.

Step 1: If you don’t have one, setup a Spring Boot project using Sping Initializr . You can use Maven or Gradle as the build tool. Step 2: Add these following dependencies to your build.gradle file
dependencies {
// Spring Boot Web implementation ‘org.springframework.boot:spring-boot-starter-web’ // Spring Data JPA (includes Hibernate) implementation 'org.springframework.boot:spring-boot-starter-data-jpa' // For PostgreSQL runtimeOnly 'org.postgresql:postgresql' // Lombok
for annotations compileOnly 'org.projectlombok:lombok' annotationProcessor 'org.projectlombok:lombok' }
Step 3: Configure your application.properties
# PostgreSQL connection spring.datasource.url =jdbc:postgresql://localhost: 5432 /mydb spring.datasource.username =postgres spring.datasource.password =yourpassword # JPA & Hibernate. # This is good
for a basic local setup. Hibernate will auto-create or
update tables
for you. # For production,
set this to 'none' and manage schema changes with migration tools like Flyway or Liquibase. spring.jpa.hibernate.ddl-auto =update

And you are good to go, now you can create an entity and a repository in your project and use it to interact with your database!

Here’s a sample end-to-end example to see how you can utilize annotations and custom methods to query the db using Spring Data JPA.

User.java

This POJO will be mapped to a database table by Hibernate, with each field corresponding to a column. We use lombok annotations to reduce boilerplate code.

@Data // Lombok annotation to generate getters, setters, toString(), equals(), and hashCode() automatically. @AllArgsConstructor // Lombok annotation that generates a constructor with all fields as arguments. @NoArgsConstructor // Lombok annotation that generates a default no-argument constructor @Entity // Marks the
class as a JPA entity - meaning Hibernate will map it to a table in the database. @Table(name = "users") // Specifies the table name in the database. If you don't use it, Hibernate will default to the
class name (User). public
class User {
@Id // JPA marks 'id' as primary key. @GeneratedValue(strategy = GenerationType.AUTO) // Decides how key will be generated. private int id;
private String name;
private String email;
private String password; }
UserController . java

The controller is the entry point for handling HTTP requests.
It exposes REST endpoints (like /users) that your frontend or API clients can call.

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.Optional; @RestController @RequestMapping("/api/users") public
class UserController {
private final UserService userService; // Constructor injection (recommended) public UserController (UserService userService) {
this .userService = userService; } // Create new user. We usually use DTOs
for request and response body. // Spring (via Jackson) will automatically deserialize 'user'
into a User
object by matching JSON keys @PostMapping public ResponseEntity<User> createUser ( @RequestBody User user) {
User savedUser userService.saveUser(user);
return ResponseEntity.ok(savedUser); } // Get user by email @GetMapping("/{email}") public ResponseEntity<User> getUserByEmail ( @PathVariable String email) {
Optional<User> user = userService.findUserByEmail(email);
return user.map(ResponseEntity::ok) .orElse(ResponseEntity.notFound().build()); } }
UserService.java

The service will handle the business logic and use the repository for database operations.

@Service // Marks this a service component and makes it a Spring Bean, so it can be injected
into controllers @Transactional // Ensures DB operations happen within a transaction. public
class UserService {
private final UserRepository userRepository; // Constructor injection (preferred) public UserService(UserRepository userRepository) {
this .userRepository = userRepository; } // Save user to DB public User saveUser(User user) {
return userRepository.save(user); } // Find user by Email public Optional<User> findUserByEmail(String email) {
return userRepository.findByEmail(email); } }
UserRepository.java

The repository will handle database interactions for the User entity and Hibernate translates these into SQL.
For example: save() in Spring Data JPA is a dual-purpose method. If the entity is new (no id yet / not present in DB) — Hibernate calls EntityManager.persist()

insert
into users (name, email, password, id)
values (?, ?, ?, ?)

If the entity already exists (has id and managed by JPA) — Hibernate calls EntityManager.merge()

update users
set name=?, email=?, password=?
where id=?

@Repository // Marks the
interface as a DAO public
interface UserRepository extends JpaRepository <User, Integer> {
Optional<User> findByEmail (String email) ; // Spring will generate a query
for you. }

When you extend JpaRepository<T, ID>, Spring gives you a full set of ready-made CRUD methods — no SQL, no implementation required.

  • save(S entity) → Insert a new entity or update if it already exists.
  • saveAll(Iterable<S> entities) → Save multiple entities at once.
  • findById(ID id) → Find entity by primary key.
  • findAll() → Get all rows.
  • findAllById(Iterable<ID> ids) → Fetch multiple by ids.
  • count() → Returns number of records in the table.
  • getOne(ID id) / getReferenceById(ID id) → Lazy-fetch a reference proxy.
  • deleteById(ID id) → Delete entity by primary key.
  • delete(T entity) → Delete given entity.
  • deleteAll(Iterable<? extends T> entities) → Bulk delete.
  • deleteAll() → Clear the whole table.

Now that you’ve integrated Hibernate with Spring Boot for basic CRUD operations, you can explore more advanced concepts to level up your skills:

  • Work with Relationships — Try mapping @OneToMany and @ManyToMany associations. Start simple before experimenting with cascade types and fetch strategies.
  • Use Database Migration Tools — In production, replace spring.jpa.hibernate.ddl-auto with tools like Flyway or Liquibase to manage schema changes safely.
  • Write Custom JPQL Queries — Go beyond method naming conventions with powerful, flexible queries using the @Query annotation.

If you found this helpful, share your thoughts in the comments, or ask a question — I’d love to hear from you. Thanks for reading!

Related Blog Posts