CodeGym /Courses /Module 5. Spring /ORM and using Hibernate with JPA in Spring

ORM and using Hibernate with JPA in Spring

Module 5. Spring
Level 5 , Lesson 1
Available

Let's dive into one of the most popular JPA implementations — Hibernate. We'll go over how it integrates with Spring, what advantages it offers, and how to set it up for your application. And to make sure you really get it, there'll be hands-on practice!


What is Hibernate?

Hibernate is an open (and free) ORM library written in Java. At first glance it might look like Hibernate is just a JPA implementation, but it's much broader and more feature-rich. It not only maps your objects to the database, but also helps optimize query execution, manage caching, provide resilience, and much more.

Benefits of Hibernate

  1. Caching: Hibernate supports multi-level caching, which speeds up access to frequently used data.
  2. Automatic DB schema generation: you can define entities and Hibernate will generate the database tables for you (yes, even without writing SQL!).
  3. Flexibility: Hibernate extends JPA capabilities with its own annotations and hybrid approaches.
  4. Support for almost any database: MySQL, PostgreSQL, Oracle — pick whatever you want.

You can think of Hibernate as a bit of a "Swiss Army knife" for database work. It handles the boring stuff so you can focus on your app's business logic!

Configuring Hibernate in Spring

Now let's move from theory to practice. We'll add Hibernate to our project using Spring Boot, configure it, and integrate it with a database.

1. Dependencies in Maven

First, make sure the needed dependencies are declared in your pom.xml:


<dependencies>
  <!-- Spring Boot Starter Data JPA -->
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
  </dependency>

  <!-- Dependency for the selected database -->
  <dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>postgresql</artifactId>
    <scope>runtime</scope>
  </dependency>
</dependencies>

For other databases (for example, MySQL, H2) add the corresponding driver instead of postgresql.

2. Configuring application.properties

The nicest thing about Spring Boot is how little effort it takes to wire up Hibernate. Most settings go in application.properties:


# Database connection configuration
spring.datasource.url=jdbc:postgresql://localhost:5432/example_db
spring.datasource.username=postgres
spring.datasource.password=password

# Specify Hibernate as the JPA provider
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect

# Automatically create/update DB schema
spring.jpa.hibernate.ddl-auto=update

# Turn on SQL logging to see the queries
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true

Key parameters here:

  • spring.datasource.url, username, password: database connection.
  • spring.jpa.database-platform: the Hibernate dialect that tells it how to work with a specific DB type.
  • spring.jpa.hibernate.ddl-auto: lets you auto-create or update tables. For example, create — recreate tables, update — apply only changes.

If you break something — don't sweat it. You can always drop the DB and migrate again!


Using Hibernate and JPA together

Hibernate extends JPA by adding extra features. So understanding both tools makes you a pro at database work.

How does Spring "manage" Hibernate?

The whole "magic" of auto-configuring Hibernate is handled by Spring Boot. On app startup Spring:

  1. Creates an instance of EntityManager to manage object-to-database mapping.
  2. Configures transactions automatically.
  3. Automatically wires repositories based on JPA interfaces.

You might not notice this work, but it's happening behind the scenes. Think of a theater crew working backstage so the actors can shine on stage — Spring Boot is that crew here, doing the heavy lifting for you.


Example: creating entities and handling them

Let's create a User entity and see how it's persisted to the database via Hibernate.

Creating the entity class


package com.example.entity;

import jakarta.persistence.*;

@Entity // Indicates that this is a JPA entity
@Table(name = "users") // Configure table name
public class User {

    @Id // Indicates the primary key
    @GeneratedValue(strategy = GenerationType.IDENTITY) // Auto-generate ID
    private Long id;

    @Column(name = "username", nullable = false, unique = true) // Column with constraints
    private String username;

    @Column(name = "email", nullable = false, unique = true)
    private String email;

    public User() {
        // No-args constructor for Hibernate
    }

    // Getters and setters (shortened for example)
    public Long getId() {
        return id;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getUsername() {
        return username;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getEmail() {
        return email;
    }
}

The next step is creating a repository to work with our User entity.


package com.example.repository;

import com.example.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    // JpaRepository already provides basic methods
    // save(), findById(), findAll(), deleteById()
}

Now let's add a couple of users to the database!


Create a small service using our repository:


package com.example.service;

import com.example.entity.User;
import com.example.repository.UserRepository;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    private final UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public User createUser(String username, String email) {
        User user = new User();
        user.setUsername(username);
        user.setEmail(email);
        return userRepository.save(user);
    }
}

And test it via a controller (or directly from main for simplicity).


package com.example;

import com.example.service.UserService;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

@Component
public class DemoRunner implements CommandLineRunner {

    private final UserService userService;

    public DemoRunner(UserService userService) {
        this.userService = userService;
    }

    @Override
    public void run(String... args) throws Exception {
        userService.createUser("john_doe", "john@example.com");
        userService.createUser("jane_doe", "jane@example.com");
        System.out.println("Users successfully added!");
    }
}

Common mistakes when working with Hibernate

One frequent issue is a database configuration error. For example, if you forget to set spring.datasource.url, the app won't be able to connect to the database. You can also get errors from a misconfigured @GeneratedValue.

Another classic mistake is forgetting the no-args constructor in entities. Hibernate requires it to create objects when loading from the database.


Practical usage

Using Hibernate in real projects helps automate repetitive database tasks. You can easily add new entities, write complex queries with JPQL, and optimize performance thanks to caching. Hibernate isn't just a tool — it's your first helper on the project.

It's good to know that Hibernate specifics are actively discussed in the official documentation and the community, which makes it an even more attractive choice for your project.

Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION