Hibernate Pagination Example

This tutorial will guide you through setting up and demonstrating pagination in Hibernate 6.4 with Java 21. We'll create a simple application that retrieves data from the database in a paginated manner, allowing you to manage large datasets efficiently.

Introduction

Pagination is essential when dealing with large datasets as it helps to retrieve data in chunks, reducing the load on the database and improving application performance. Hibernate provides built-in support for pagination through the Query interface.

In this tutorial, we will:

  1. Set up a Maven project with Hibernate and an H2 database dependency.
  2. Configure Hibernate.
  3. Create an entity class (User).
  4. Implement methods to retrieve paginated results.
  5. Demonstrate pagination with a sample application.

Step 1: Set Up Your Project

1.1 Create a Maven Project

Open your IDE and create a new Maven project.

1.2 Add Dependencies

Update your pom.xml file to include the necessary dependencies for Hibernate and H2 (an in-memory database for simplicity).

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>hibernate-pagination-example</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <!-- Hibernate ORM -->
        <dependency>
            <groupId>org.hibernate.orm</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>6.4.0.Final</version>
        </dependency>

        <!-- H2 Database -->
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <version>2.1.214</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.10.1</version>
                <configuration>
                    <source>21</source>
                    <target>21</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

1.3 Configure Hibernate

Create a file named hibernate.cfg.xml in the src/main/resources directory to configure Hibernate. This file contains the database connection settings and Hibernate properties.

<!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
    <session-factory>
        <property name="hibernate.dialect">org.hibernate.dialect.H2Dialect</property>
        <property name="hibernate.connection.driver_class">org.h2.Driver</property>
        <property name="hibernate.connection.url">jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1</property>
        <property name="hibernate.connection.username">sa</property>
        <property name="hibernate.connection.password"></property>
        <property name="hibernate.hbm2ddl.auto">update</property>
        <property name="hibernate.show_sql">true</property>
    </session-factory>
</hibernate-configuration>

Explanation:

  • hibernate.dialect specifies the SQL dialect to be used.
  • hibernate.connection.driver_class specifies the JDBC driver class.
  • hibernate.connection.url specifies the JDBC URL for the database connection.
  • hibernate.connection.username and hibernate.connection.password specify the database credentials.
  • hibernate.hbm2ddl.auto specifies the schema generation strategy.
  • hibernate.show_sql specifies whether to show SQL statements in the logs.

Step 2: Create the Entity Class

Create an entity class User that will be mapped to a table in the database. This class uses annotations to define the entity and its fields.

package com.example.entity;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String email;

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

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

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

Explanation:

  • The @Entity annotation specifies that the class is an entity and is mapped to a database table.
  • The @Id annotation specifies the primary key of the entity.
  • The @GeneratedValue(strategy = GenerationType.IDENTITY) annotation specifies that the primary key is auto-incremented.

Step 3: Create the Hibernate Utility Class

Create a utility class HibernateUtil to manage the Hibernate SessionFactory. This class ensures a single instance of SessionFactory is created and provides a method to close it.

package com.example.util;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtil {
    private static final SessionFactory sessionFactory = buildSessionFactory();

    private static SessionFactory buildSessionFactory() {
        try {
            // Create the SessionFactory from hibernate.cfg.xml
            return new Configuration().configure().buildSessionFactory();
        } catch (Throwable ex) {
            // Make sure you log the exception, as it might be swallowed
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }

    public static void shutdown() {
        // Close caches and connection pools
        getSessionFactory().close();
    }
}

Explanation:

  • The buildSessionFactory method creates the SessionFactory from the hibernate.cfg.xml configuration file.
  • The getSessionFactory method returns the singleton instance of SessionFactory.
  • The shutdown method closes the SessionFactory to release resources.

Step 4: Implement Pagination

Create a class UserService to handle database operations with pagination. This class includes a method to retrieve paginated results.

package com.example.service;

import com.example.entity.User;
import com.example.util.HibernateUtil;
import org.hibernate.Session;
import org.hibernate.query.Query;

import java.util.List;

public class UserService {

    public List<User> getUsers(int pageNumber, int pageSize) {
        Session session = HibernateUtil.getSessionFactory().openSession();
        List<User> users = null;

        try {
            String hql = "FROM User";
            Query<User> query = session.createQuery(hql, User.class);
            query.setFirstResult((pageNumber - 1) * pageSize);
            query.setMaxResults(pageSize);
            users = query.list();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            session.close();
        }

        return users;
    }
}

Explanation:

  • The getUsers method opens a Hibernate session and creates a query to retrieve User entities.
  • The setFirstResult method sets the starting position of the first result.
  • The setMaxResults method sets the maximum number of results to retrieve.
  • The query is executed, and the results are returned as a list.

Step 5: Demonstrate Pagination

Create a MainApp class to demonstrate the pagination functionality. This class calls the getUsers method of UserService to retrieve paginated results.

package com.example.main;

import com.example.entity.User;
import com.example.service.UserService;

import java.util.List;

public class MainApp {
    public static void main(String[] args) {
        UserService userService = new UserService();

        // Add some users to the database (for demonstration purposes)
        for (int i = 1; i <= 50; i++) {
            userService.createUser("User" + i, "user" + i + "@example.com");
        }

        // Retrieve paginated results
        int pageNumber = 1;
        int pageSize = 10;
        List<User> users = userService.getUsers(pageNumber, pageSize);

        // Print the retrieved users
        System.out.println("Page " + pageNumber + " of users:");
        for (User user : users) {
            System.out.println(user.getId() + " - " + user.getName() + " - " + user.getEmail());
        }
    }
}

Explanation:

  1. Create a UserService Instance:

    UserService userService = new UserService();
    

    An instance of UserService is created to call its methods for performing database operations.

  2. Add Users to the Database:

    for (int i = 1; i <= 50; i++) {
        userService.createUser("User" + i, "user" + i + "@example.com");
    }
    

    A loop is used to add 50 users to the database for demonstration purposes.

  3. Retrieve Paginated Results:

    int pageNumber = 1;
    int pageSize = 10;
    List<User> users = userService.getUsers(pageNumber, pageSize);
    

    The getUsers method is called with pageNumber and pageSize parameters to retrieve the first page of users, with 10 users per page.

  4. Print the Retrieved Users:

    System.out.println("Page " + pageNumber + " of users:");
    for (User user : users) {
        System.out.println(user.getId() + " - " + user.getName() + " - " + user.getEmail());
    }
    

    The retrieved users are printed to the console.

Sample Output

When you run the MainApp class, you should see the following output:

Page 1 of users:
1 - User1 - user1@example.com
2 - User2 - user2@example.com
3 - User3 - user3@example.com
4 - User4 - user4@example.com
5 - User5 - user5@example.com
6 - User6 - user6@example.com
7 - User7 - user7@example.com
8 - User8 - user8@example.com
9 - User9 - user9@example.com
10 - User10 - user10@example.com

This output indicates that the first page of users was successfully retrieved and printed, with 10 users per page.

Conclusion

In this tutorial, we have successfully demonstrated how to implement pagination in Hibernate. We set up a Hibernate project, created an entity class, and implemented pagination functionality. This guide provides a solid foundation for managing large datasets efficiently in your Hibernate-based applications.

Comments