How to setup Pagination in Spring Boot and Hibernate

Implement pagination in APIs

When dealing with large amounts of data in a front-end application, we often need to break it down to smaller chucks so as to not overwhelm the user. Hence in front-end application we display large chucks of data as pages. Using this technique, we can request only required data for displaying only a single page at a time. To achieve this, we require pagination in API requests

Spring boot makes it easy to setup pagination with hibernate.

1. First we need to create the entity,

Entity
@Table(name = "test_details")
public class TestDetails {
	@Id
	@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "test_id")
	@SequenceGenerator(name = "test_id", sequenceName = "test_id", allocationSize = 1)
	@Column(name = "test_id")
	private Integer testId;

	@Column(name = "test_name")
	private String testName;

	public TestDetails() {
	}

	public Integer getTestId() {
		return testId;
	}

	public void setTestId(Integer testId) {
		this.testId = testId;
	}

	public String getTestName() {
		return testName;
	}

	public void setTestName(String testName) {
		this.testName = testName;
	}
}

2. Then create the repository. Here it should extend PagingAndSortingRepository

@Repository
public interface TestRepository extends PagingAndSortingRepository<TestDetails,Integer>{
	@Query(value="SELECT u FROM TestDetails u order by u.testId ASC")
	List<TestDetails> getAllTests(Pageable pageable);
}

3. Now create a PageRequest object and pass it to the above repository method

PageRequest.of(pageNum-1, pageSize)

Here PageRequest starts from zeroth index, hence if user passes pageNum parameter as 1, to get the first set of data, we subtract it by 1.

4. Finally write the implementation method as follows,

@Override
    public List<TestDetails> getTests(Integer pageNum, Integer pageSize) throws TestNotFoundExpection {
    	List<TestDetails> testDetailsList = testRepository.getAllTests(PageRequest.of(pageNum-1, pageSize));
    	if(testDetailsList.size()>0) {
    		return testDetailsList;
    	}
    	}else {
    		throw new TestNotFoundExpection("No Test in page number "+pageNum);
    	}
    }

Common error observed:

If there are any entities with 1:M relation within TestDetails entity we might get below error,

[org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: TestDetails.items

To resolve this error, declare implementation method as @Transactional

@Transactional
@Override
    public List<TestDetails> getTests(Integer pageNum, Integer pageSize) throws TestNotFoundExpection {
        List<TestDetails> testDetailsList = testRepository.getAllTests(PageRequest.of(pageNum-1, pageSize));
        if(testDetailsList.size()>0) {
    		return testDetailsList;
    	}
    	}else {
    		throw new TestNotFoundExpection("No Test in page number "+pageNum);
    	}
    }

Hope this article provides a primer on implementing API pagination using Spring boot

Checkout more Java related articles here