Hibernate with Spring Boot: Step-by-Step Integration Guide

Illustration for Hibernate with Spring Boot: Step-by-Step Integration Guide
By Last updated:

Hibernate is one of the most widely used ORM (Object Relational Mapping) frameworks in Java, and Spring Boot simplifies application development with powerful auto-configuration and dependency injection. Combining them allows developers to build scalable, data-driven applications efficiently.

Think of Hibernate as the translator between Java objects and database tables, while Spring Boot is the orchestrator that sets up everything seamlessly.

In this tutorial, we’ll integrate Hibernate with Spring Boot step by step, from setup to CRUD operations, queries, and best practices.


Why Use Hibernate with Spring Boot?

  • Simplified configuration with application.properties or application.yml.
  • Auto-wiring of SessionFactory and EntityManager.
  • Easy integration with Spring Data JPA.
  • Support for transactions with @Transactional.
  • Cleaner code with annotations.

Project Setup

Maven Dependencies

Add these to your pom.xml:

<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.mysql</groupId>
        <artifactId>mysql-connector-j</artifactId>
        <scope>runtime</scope>
    </dependency>
</dependencies>

Application Properties

spring.datasource.url=jdbc:mysql://localhost:3306/hibernatedb
spring.datasource.username=root
spring.datasource.password=yourpassword

spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect

Creating an Entity

import jakarta.persistence.*;

@Entity
@Table(name = "employees")
public class Employee {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    private String department;

    private double salary;

    // getters and setters
}

Repository Layer

Spring Data JPA makes repository creation effortless.

import org.springframework.data.jpa.repository.JpaRepository;

public interface EmployeeRepository extends JpaRepository<Employee, Long> {
    List<Employee> findByDepartment(String department);
}

Service Layer

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class EmployeeService {

    private final EmployeeRepository repository;

    public EmployeeService(EmployeeRepository repository) {
        this.repository = repository;
    }

    @Transactional
    public Employee save(Employee emp) {
        return repository.save(emp);
    }

    public List<Employee> findAll() {
        return repository.findAll();
    }

    public List<Employee> findByDepartment(String dept) {
        return repository.findByDepartment(dept);
    }

    @Transactional
    public void delete(Long id) {
        repository.deleteById(id);
    }
}

Controller Layer

import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/employees")
public class EmployeeController {

    private final EmployeeService service;

    public EmployeeController(EmployeeService service) {
        this.service = service;
    }

    @PostMapping
    public Employee create(@RequestBody Employee emp) {
        return service.save(emp);
    }

    @GetMapping
    public List<Employee> getAll() {
        return service.findAll();
    }

    @GetMapping("/{dept}")
    public List<Employee> getByDepartment(@PathVariable String dept) {
        return service.findByDepartment(dept);
    }

    @DeleteMapping("/{id}")
    public void delete(@PathVariable Long id) {
        service.delete(id);
    }
}

Querying with Hibernate

You can use HQL, Criteria API, or native SQL queries.

HQL Example

@Query("SELECT e FROM Employee e WHERE e.salary > :salary")
List<Employee> findHighEarners(@Param("salary") double salary);

Native SQL Example

@Query(value = "SELECT * FROM employees WHERE department = ?1", nativeQuery = true)
List<Employee> findByDepartmentNative(String dept);

Caching and Performance

Enable second-level cache for performance optimization.

spring.jpa.properties.hibernate.cache.use_second_level_cache=true
spring.jpa.properties.hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory

This allows frequently accessed entities to be cached.


Common Pitfalls & Anti-Patterns

  1. N+1 Select Problem → Use fetch joins or @BatchSize.
  2. Eager Fetching Everywhere → Can cause memory overhead. Prefer LAZY.
  3. Long Transactions → Can lead to locks and poor performance.
  4. Improper Cascade Usage → Leads to unintended deletions.

Best Practices

  • Use Spring Data JPA for repositories.
  • Keep entity classes simple and focused.
  • Apply transaction boundaries at the service layer.
  • Monitor SQL logs to catch N+1 problems early.
  • Use second-level cache wisely.

📌 Hibernate Version Notes

Hibernate 5.x

  • Uses javax.persistence.
  • SessionFactory setup with XML or Spring Boot auto-config.
  • Well-supported in legacy Spring Boot apps.

Hibernate 6.x

  • Migrated to jakarta.persistence.
  • Improved SQL support and query plan caching.
  • Better Criteria API and fetch strategies.
  • Native integration with Spring Boot 3.x.

Conclusion & Key Takeaways

  • Hibernate + Spring Boot = powerful and efficient integration.
  • Setup is simplified via spring-boot-starter-data-jpa.
  • Entities map Java objects to database tables seamlessly.
  • CRUD operations become effortless with Spring Data repositories.
  • Avoid pitfalls like N+1 and eager fetching for scalable apps.

FAQ: Expert-Level Questions

Q1: What’s the difference between Hibernate and JPA?
Hibernate is a JPA implementation with extended features.

Q2: How does Hibernate caching improve performance?
By storing frequently accessed data in memory (L1, L2 cache).

Q3: What are the drawbacks of eager fetching?
It can load unnecessary data, causing performance and memory issues.

Q4: How do I solve the N+1 select problem in Hibernate?
Use fetch joins, batch fetching, or entity graphs.

Q5: Can I use Hibernate without Spring?
Yes, Hibernate can run standalone using SessionFactory.

Q6: What’s the best strategy for inheritance mapping?
Depends: SINGLE_TABLE for speed, JOINED for normalization, TABLE_PER_CLASS for isolation.

Q7: How does Hibernate handle composite keys?
By using @Embeddable with @EmbeddedId or @IdClass.

Q8: How is Hibernate 6 different from Hibernate 5?
Hibernate 6 uses jakarta.persistence, has better SQL generation, and integrates with Spring Boot 3.

Q9: Is Hibernate suitable for microservices?
Yes, but smaller ORMs like jOOQ or MyBatis may suit some microservices better.

Q10: When should I not use Hibernate?
Avoid it in performance-critical apps requiring fine-grained SQL control (e.g., analytics systems).