How to Add Dynamic Pagination in Spring Boot using Spring Data JPA

How to display a large set of the Object or List into pagination form Using Spring boot. This detailed Spring tutorial will help you to implement the Implementation of pagination using Spring Data JPA in the spring boot application.

What is Pagination?

When we have a large set of data available in the database and want to display it in a certain amount, then we use this concept called Pagination. Consider an example, If you search for something on Google search engine, it does not give you all the data at once, It divides the data and shows us a chunk of data, and with the help of the next/previous link we see data. So, this is nothing but Pagination.

How to do Pagination using Spring Data JPA?

In Spring Data JPA, we have a PagingAndSortingRepository interface that contains the following methods:

  • findAll(Sort sort): This method returns all results in sorted form.
  • findAll(Pageable pageable): This method is used for pagination.

Following are the steps we need to follow in order to perform Pagination:

  1. Create an object of PageRequest class. It accepts two fields; one is the page number and another one is the page size.
  2. Pass the PageRequest object to the repository method.
  3. Consider, we have a repository method findAll(Pageable pageable) that will return Page object. Thus, this page object will return the list.

Example to perform Pagination using Spring Data JPA in Spring boot application

Tools & Technologies used:

  • Spring Boot
  • Spring Data JPA
  • Thymeleaf

Step 1: Open IDE STS- Spring Tool Suite

Step 2: Go to File > Spring Starter Project.

Step 3: Now, fill all the fields as shown below and click Next.

Step 4: Now, Add the dependencies of spring data JPA, Thymeleaf MYSQL Driver, Lombok, and spring web.

Now, wait for some time and your project structure will be ready. Go to the pom.xml file and you will see the following dependencies will be added automatically.

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
   <scope>runtime</scope>
</dependency>

Create a Database in MYSQL

mysql> create database db_demo;

Configure application. properties file

spring.jpa.hibernate.ddl-auto=update
spring.datasource.url=jdbc:mysql://localhost:3306/db_demo
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name =com.mysql.jdbc.Driver
spring.jpa.show-sql= true
## Hibernate Properties
# The SQL dialect makes Hibernate generate better SQL for the chosen database
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDialect
#To format SQL queries generated by Hibernate
spring.jpa.properties.hibernate.format_sql=true
#change port number
server.port=8888
  • spring.jpa.hibernate.ddl-auto is set to update so that whatever changes we will do will be reflected in the schema.
  • spring.datasource.url is used to set the URL of the MYSQL DB.
  • spring.datasource.username is used to set the username and spring. datasource. password is used to set the password.
  • spring.datasource.driver-class-name is used to set the driver class name.
  • spring.jpa.show-sql is set to true to show SQL generated by the Hibernate.
  • spring.jpa.properties.hibernate.dialect is used to generate better SQL for the chosen database.
  • spring.jpa.properties.hibernate.format_sql is set to true to format SQL queries.
  • server.port is set to 8888.

Create an Entity Class

Doctor.java

package com.abc.example.model;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

import lombok.Getter;
import lombok.Setter;

@Setter
@Getter
@Entity
@Table(name = "doctor")
public class Doctor {

 @Id
 @GeneratedValue(strategy = GenerationType.IDENTITY)
 private long id;
 @Column(name = "doctor_name")
 private String doctorName;
 @Column(name = "age")
 private int doctorAge;
 @Column(name = "dob")
 private String dob;
 @Column(name = "specialist")
 private String specialist;
 
 
}
  • @Entity is used to annotate the classes to indicate that they are JPA entities.
  • @Table annotation is used to specify the name of the table that should be mapped with entities.
  • @Id annotation is used for the primary key.
  • I have used the Lombok library to remove boilerplate code. In case you want to know what is Lombok check this article https://codedec.com/tutorials/how-to-configure-lombok-into-eclipse/

Create Repository Interface

The repository here is the DAO layer, which performs all the database operations. DoctorRepository interface is created which will extend JPARepository<ClassName, ID>.

package com.abc.example.reporsitory;

import org.springframework.data.domain.Page;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import com.abc.example.model.Doctor;

@Repository
public interface DoctorRepository extends JpaRepository<Doctor, Long> {	
}

Create a Service Layer

DoctorService

package com.abc.example.service;

import org.springframework.data.domain.Page;

import com.abc.example.model.Doctor;

public interface DoctorService {
 Page<Doctor> findByPagination(int pageNo, int size);

}

DoctorServiceImpl.java

package com.abc.example.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import com.abc.example.model.Doctor;
import com.abc.example.reporsitory.DoctorRepository;
@Service
public class DoctorServiceImpl implements DoctorService {

 @Autowired
 private DoctorRepository repo;
 @Override
 public Page<Doctor> findByPagination(int pageNo, int size) {
  // TODO Auto-generated method stub
  Pageable pageable = PageRequest.of(pageNo-1,size);
  return repo.findAll(pageable);
 }

}
  • PageRequest class is passed with the requested page number and page size.
  • We have passed the PageRequest object to the repository method.

Create a Controller class

The request for the web page will be handle by the handler methods in the controller class using @GetMapping.

package com.abc.example.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

import com.abc.example.model.Doctor;
import com.abc.example.service.DoctorService;

@Controller
public class DoctorController {

 @Autowired
 private DoctorService service;
 
 @GetMapping("/")
 public String home(Model m) {
  return display(1, m);
  
 }
 
 @GetMapping("/page/{pageNo}")
 public String display(@PathVariable (value = "pageNo") int pageNo, Model m) {
  int pageSize = 2;   // How many records on per page
  Page<Doctor> page= service.findByPagination(pageNo, pageSize);
  List<Doctor> list = page.getContent();
  m.addAttribute("currentPage", pageNo);
  m.addAttribute("totalPages", page.getTotalPages());
  m.addAttribute("totalRecords", page.getTotalElements());
  m.addAttribute("list", list);
  return "index";
  
 }
}

The current page and page size is changed using pageNo and size.

  • pageNo – current page number.
  • pageSize – record per page. (Here, we have set it to 2)

Create View using Thymeleaf

Go to src/main/resources/template folder and create an index.html file

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="ISO-8859-1">
<title>Pagination</title>
<!-- CSS only -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<!-- JavaScript Bundle with Popper -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
</head>
<body style="background-color: #FEDBD0">
<div class="container">
<h1 align="center">List of Doctors</h1>
<table class="table">
  <thead class="table-primary">
    <tr>
      <th scope="col">#</th>
      <th scope="col">Doctor Name</th>
      <th scope="col">Doctor DOB</th>
      <th scope="col">Age</th>
      <th scope="col">Specialist</th>
    </tr>
  </thead>
  <tbody>
   <tr th:each="doctor: ${list}">
   <td th:text="${doctor.id}"></td>
   	<td th:text="${doctor.doctorName}"></td>
   	<td th:text="${doctor.dob}"></td>
   	<td th:text="${doctor.doctorAge}"></td>
   	<td th:text="${doctor.specialist}"></td>
   </tr>   
  </tbody>
</table>
<div th:if="${totalPages > 1}"></div>
 <div class="row col-sm-10">
  <div class="col-sm-2">Pagination</div>	
  <div class="col-sm-1 page-item">
 <div class="col-sm-1 page-item">
  <a th:if="${currentPage==1}" >Previous</a>
  <a th:if="${currentPage!=1}" th:href="@{'/page/'+${currentPage - 1}}">Previous</a>
  
  </div>
  
  
  </div>
  
  <div class="col-sm-1">
  <span class="page-item" th:each="i: ${#numbers.sequence(1,totalPages)}">
  <a th:if="${currentPage!=i}" th:href="@{'/page/'+${i}}">[[${i}]]</a>
  <span th:unless="${currentPage!=i}">[[${i}]]</span>
  </span>
   
  </div>
  <div class="col-sm-1 page-item">
  <a th:if="${currentPage < totalPages}" th:href="@{'/page/'+${currentPage + 1}}">Next</a>
  <span class="page-item" th:unless="${currentPage < totalPages}">Next</span>
  </div>
  <div class="col-sm-1">
  <a th:if="${currentPage < totalPages}" th:href="@{'/page/'+${totalPages}}">Last</a>
  <span class="page-item" th:unless="${currentPage < totalPages}">Last</span>
  </div>
 </div>
</div>
</body>
</html>

Now, Run the PaginationSpringDataJpaApplicationclass and Go to localhost:8888 and see the following output.

In this way, we perform pagination using spring data JPA in a spring boot application.

Major projects in Spring boot for Placement

If you are preparing for any technical interview or doing an internship these projects will add more starts in your resume. Available project in Spring