Introduction to JPA and Hibernate with Spring Boot

Saquib Khan
5 min readApr 27, 2024

The Java Persistence API (JPA), now evolving under the name Jakarta Persistence API as part of the Jakarta EE platform, is a Java specification for accessing, persisting, and managing data between Java objects and relational databases. It serves as an abstraction layer that allows developers to work with data as objects without the need to directly handle the underlying database and SQL queries.

This shift to using the name “Jakarta” reflects the transition of the management and stewardship of the enterprise Java standards from Oracle to the Eclipse Foundation, which aims to advance Java EE technologies under an open and collaborative community. The Jakarta Persistence API continues the legacy of JPA by providing robust, scalable, and flexible ORM solutions in the Java ecosystem.

Hibernate is one of the most popular implementations of JPA. It simplifies database interactions, automatically handling CRUD (Create, Read, Update, Delete) operations and more. Hibernate manages relational data as complex Java objects, providing a more intuitive approach to data handling.

Spring Boot makes it easy to create stand-alone, production-grade Spring-based applications. It simplifies the setup and development of new applications by providing defaults for code and configuration and a range of tools and plugins for development tasks.

Setting Up Your Environment

Before diving into coding, you’ll need to set up your development environment:

  1. Java Development Kit (JDK): Install JDK 11 or later from Oracle’s website or through any OpenJDK distribution.
  2. Integrated Development Environment (IDE): Use an IDE like IntelliJ IDEA, Eclipse, or Spring Tool Suite for efficient coding.
  3. Maven or Gradle: These are build tools that manage project dependencies and build configurations. Spring Boot supports both.
  4. Spring Initializr: Use Spring Initializr to generate your project structure.

Project Setup with Spring Boot

Start your project setup using Spring Initializr:

Project: Choose Maven or Gradle

Language: Java

Spring Boot version: Choose the latest stable release

Project Metadata:

  • Group: com.example
  • Artifact: demo
  • Name: DemoApplication
  • Description: Demo project for Spring Boot with JPA and Hibernate
  • Package name: com.example.demo

Dependencies: Add ‘Spring Web’, ‘Spring Data JPA’, and ‘MySQL Driver’ or ‘H2 Database’ for in-memory DB testing.

We will see the working with simple CRUD application of Users:

Step 1: Define the DAO Interface

First, let’s define a DAO interface for managing user entities. This interface will include methods for typical CRUD operations.

public interface UserDAO {
User findById(Long id);
List<User> findAll();
void save(User user);
void update(User user);
void delete(Long id);
}

Step 2: Implement the DAO Interface

Next, we’ll create an implementation of the UserDAO that uses JPA EntityManager for persistence operations.

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.transaction.Transactional;
import java.util.List;

public class UserDAOImpl implements UserDAO {
@PersistenceContext
private EntityManager entityManager;
@Override
@Transactional
public User findById(Long id) {
return entityManager.find(User.class, id);
}
@Override
@Transactional
public List<User> findAll() {
return entityManager.createQuery("from User", User.class).getResultList();
}
@Override
@Transactional
public void save(User user) {
entityManager.persist(user);
}
@Override
@Transactional
public void update(User user) {
entityManager.merge(user);
}
@Override
@Transactional
public void delete(Long id) {
User user = findById(id);
if (user != null) {
entityManager.remove(user);
}
}
}

Step 3: Configure DAO as a Spring Bean

Ensure that the DAO is recognized as a Spring bean. This can be done by annotating the implementation with @Repository and ensuring it's scanned by Spring's component scanning.

import org.springframework.stereotype.Repository;

@Repository
public class UserDAOImpl implements UserDAO {
// implementation details
}

Step 4: Use CommandLineRunner

Now, we’ll create a CommandLineRunner that uses this DAO to perform some database operations when the application starts. This is useful for demonstrating or testing the DAO methods without building a user interface.

package com.saquib.cruddemo;

import com.saquib.cruddemo.dao.UserDAO;
import com.saquib.cruddemo.entity.User;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import java.util.List;

@SpringBootApplication
public class CruddemoApplication {

public static void main(String[] args) {
SpringApplication.run(CruddemoApplication.class, args);
}

@Bean
public CommandLineRunner commandLineRunner(UserDAO userDAO) {
return args -> {
// Create a new user
System.out.println("Creating new user object...");
User newUser = new User("Paul", "Doe", "paul@luv2code.com");
userDAO.save(newUser);
System.out.println("Saved Student. Generated id: " + newUser.getId());

// Update the user
System.out.println("Updating user...");
newUser.setEmail("new.paul.doe@example.com");
userDAO.update(newUser);

// Find user by id
System.out.println("Getting user with id: " + newUser.getId());
User foundUser = userDAO.findById(newUser.getId());
System.out.println("Found User: " + foundUser.getEmail());

// List all users
System.out.println("Listing all users...");
List<User> users = userDAO.findAll();
users.forEach(user -> System.out.println(user.getName()));

// Delete the user
System.out.println("Deleting user id: " + newUser.getId());
userDAO.delete(newUser.getId());

// Optional: Clean up - Delete all users
System.out.println("Deleting all users...");
userDAO.deleteAll();
};
}
}

Here are a few scenarios where Hibernate excels:

  • Complex Transactions: Hibernate handles complex transactions smoothly with its advanced transaction management capabilities.
  • Dynamic Queries: Use Hibernate’s Criteria API for building type-safe queries dynamically.
  • Caching: Hibernate’s second-level cache helps in optimizing read-heavy operations.

Here are some noteworthy alternatives to Hibernate:

1. EclipseLink

  • Overview: EclipseLink is the reference implementation of the JPA specification. It was originally developed by Oracle as TopLink and later contributed to the Eclipse Foundation.
  • Features: It supports flexible caching configurations, XML and JSON binding, and more extensive customization options than Hibernate.
  • Use Cases: It’s well-suited for applications that require robust XML or JSON integration or those utilizing Oracle databases where advanced Oracle-specific features are needed.

2. Apache OpenJPA

  • Overview: OpenJPA is another popular JPA implementation that is used in various open-source projects, including Apache Geronimo and IBM WebSphere.
  • Features: OpenJPA provides support for distributed architectures and large-scale applications.
  • Use Cases: It’s typically used in enterprise applications, especially where integration with Apache software is beneficial.

3. DataNucleus

  • Overview: DataNucleus provides JPA, JDO (Java Data Objects), and REST persistence layers. It’s known for its compliance with both JPA and JDO specifications.
  • Features: One of its main strengths is its support for a wide variety of datastores including relational, web-based, document-based, column-based, and file-based types.
  • Use Cases: It is particularly useful for applications requiring support for non-relational databases in addition to JPA functionality.

4. MyBatis

  • Overview: MyBatis is not a JPA implementation but a persistence framework that maps classes to SQL statements. It allows for more direct control over SQL compared to JPA.
  • Features: Offers detailed control over SQL and is excellent at handling existing legacy databases where changing schema is not feasible.
  • Use Cases: Best for applications requiring intense SQL optimization or where the database schema is complex and does not fit well with an ORM model.

Conclusion

JPA and Hibernate form a powerful duo for ORM in Java applications. Whether you’re building a small microservice or a large enterprise application, understanding and implementing these technologies can lead to cleaner, more efficient, and scalable code. As you continue exploring, remember to delve deeper into topics such as caching strategies, query optimization, and advanced mappings to fully leverage the power of Hibernate in your projects.

--

--