Spring Data Solr

Spring Data Solr Pagination Example

In this article of the Spring Data Solr Pagination, we will discuss how to paginate Solr query results in the spring application. Spring Data provides PageRequest class which extends AbstractPageRequest and this abstract class implements the Pageable interface. We can query to fetch Solr results in pagination by using PageRequest class from the service layer.

Using Spring Data Solr Pagination

Spring Data provides a generic way of pagination implementation in the spring application for all Spring Data implementation such as Spring Data Solr, Spring Data Cassandra, Spring Data JPA etc. But in this article, we will look into pagination implementation by using the Spring Data Solr.

Creating PageRequest object for pagination

Since Spring Data 2.0, creating a new PageRequest object using constructors is deprecated. Instead of the PageRequest constructor, we can use of() static method as a factory method to create a PageRequest object. In a PageRequest object, pages are zero indexed, thus providing 0 for a page will return the first page.

We can create the PageRequest objects by using several provided overloaded version of the of() method. This object fulfils the pagination requirements as following:

Requirement 1

If you want to create a PageRequest object to specify a query results belonging to a single page. Then we have to create the PageRequest object as the following code snippet:

public static PageRequest of(int page, int size) {
     //implementation
}

//In-service class get the query results belonging to the first page when page size is 10.
PageRequest.of(0, 10)

Requirement 2

Another way, if you want to create a PageRequest object to specify the results belonging to a single page but the query results are sorted by using the value of a single field, we have discussed about Spring Data Solr Sorting in the previous article. Let’s see the following code snippet to create PageRequest object:

public static PageRequest of(int page, int size, Sort sort) {
     //implementation
}

//In-service class get the query results belonging to the first page when page size is 10.
//Query results are sorted in descending order by using a price field.
PageRequest.of(0, 10 Sort.Direction.DESC, "price")

Requirement 3

In this requirement, if you want to create a PageRequest object to specify the query results belonging to a single page but the query results are sorted by using multiple fields and sort order of different fields is same. Let’s see the following code snippet to create PageRequest object:

public static PageRequest of(int page, int size, Direction direction, String... properties) {
     //implementation
}

//In-service class get the query results belonging to the first page when page size is 10.
//Query results are sorted in descending order by using oid and odesc fields.
PageRequest.of(0, 10 Sort.Direction.DESC, "oid", "odesc")

Requirement 4

This requirement is very suitable when we want to create a PageRequest object to specify the query results belonging to a single page when the query results are sorted by using multiple fields and the sort order of different fields is not same. Let’s see the following code snippet to create PageRequest object:

public static PageRequest of(int page, int size, Direction direction, String... properties) {
     //implementation
}

//In-service class get the query results belonging to the first page when page size is 10.
//Query results are sorted in descending order by using oid field and ascending order by using odesc field.
Sort sort = Sort.by(Sort.Direction.DESC, "oid").and(Sort.by(Sort.Direction.ASC, "odesc"))
PageRequest.of(0, 10, sort)

We have discussed how to create a new PageRequest object using several flavours of the of() method of PageRequest class. The Solr query with the Pageable object return the results with following return types.

A return type of a Paginated Solr Query

In the Spring Data Solr. if you use a query method with pagination, it can have query result into two types. Let’s see these return types of the paginated query method.

  • Page<Order>: If you want pagination metadata along with query result then you have to use this return type. Here the Page is an interface of the Spring Data module and it declares the methods used to fetch pagination metadata in the application.
  • List<Order>: If you want the only content of results of the paginated Solr query then you have to use this return type

Let’s see an example of a Spring Data repository with the pagination implementation.

Spring Data Solr Repository Example

In the following repository interface, we have created a repository interface with query generation from the query method.

Query Generation From Method Name

In this step, we will explain how to create a query from the method name strategy. Let’s see the following code:

package com.doj.app.repository;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.solr.repository.SolrCrudRepository;

import com.doj.app.pojo.Order;

/**
 * @author Dinesh.Rajput
 *
 */
public interface SolrOrderRepository extends SolrCrudRepository<Order, Long> {
	
    Page<Order> findByOrderDescription(String searchTerm, Pageable pageable);
    
}

In the above code, we have created an interface SolrOrderRepository, and we have to add a Pageable parameter to the findByOrderDescription() method of this interface. Let’s see sorting using @Query annotation as the following code:

Using @Query Annotation

Here we create a method annotated with the @Query annotation. Let’s see the following code:

package com.doj.app.repository;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.solr.repository.Query;
import org.springframework.data.solr.repository.SolrCrudRepository;

import com.doj.app.pojo.Order;

/**
 * @author Dinesh.Rajput
 *
 */
public interface SolrOrderRepository extends SolrCrudRepository<Order, Long> {
    
    @Query("odesc:*?0*") 	
    Page<Order> findByOrderDescription(String searchTerm, Pageable pageable);
    
}

In the above code, we have created a method annotated with the @Query annotation. And we have also added a Pageable parameter to the findByOrderDescription() method of the SolrOrderRepository interface.

Named Queries

Let’s see the named queries method.

package com.doj.app.repository;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.solr.repository.Query;
import org.springframework.data.solr.repository.SolrCrudRepository;

import com.doj.app.pojo.Order;

/**
 * @author Dinesh.Rajput
 *
 */
public interface SolrOrderRepository extends SolrCrudRepository<Order, Long> {
    
   @Query(name = "Product.findByNamedQuery")
   Page<Product> findByNamedQuery(String searchTerm, Pageable pageable);
    
}

In the above code, we have used the named queries and we have added a Pageable parameter to the findByNamedQuery() method. In the next section, we will discuss how to call this repository using either controller layer or service layer as the following code:

package com.doj.app.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import com.doj.app.pojo.Order;
import com.doj.app.repository.SolrOrderRepository;

/**
 * @author Dinesh.Rajput
 *
 */
@RestController
public class OrderController {
	
	@Autowired
	SolrOrderRepository solrOrderRepository;
	
	...
	
	@GetMapping("/order/desc/{orderDesc}/{page}")
	public List<Order> findOrder(@PathVariable String orderDesc, @PathVariable int page){
		return solrOrderRepository.findByOrderDescription(orderDesc, PageRequest.of(page, 2)).getContent();
	}
	
	@GetMapping("/order/search/{searchTerm}/{page}")
	public List<Order> findOrderBySearchTerm(@PathVariable String searchTerm, @PathVariable int page){
		return solrOrderRepository.findByCustomerQuery(searchTerm, PageRequest.of(page, 2)).getContent();
	}
	
	...
}

As you can see in the above code, how we have used the paginated request from the controller layer by passing the Pageable object to the repository method.

Summary

In this article, we have learned about how to create a paginated query in the Spring Data Solr example by using the PageRequest class and Pageable interface.

Previous
Next
Dinesh Rajput

Dinesh Rajput is the chief editor of a website Dineshonjava, a technical blog dedicated to the Spring and Java technologies. It has a series of articles related to Java technologies. Dinesh has been a Spring enthusiast since 2008 and is a Pivotal Certified Spring Professional, an author of a book Spring 5 Design Pattern, and a blogger. He has more than 10 years of experience with different aspects of Spring and Java design and development. His core expertise lies in the latest version of Spring Framework, Spring Boot, Spring Security, creating REST APIs, Microservice Architecture, Reactive Pattern, Spring AOP, Design Patterns, Struts, Hibernate, Web Services, Spring Batch, Cassandra, MongoDB, and Web Application Design and Architecture. He is currently working as a technology manager at a leading product and web development company. He worked as a developer and tech lead at the Bennett, Coleman & Co. Ltd and was the first developer in his previous company, Paytm. Dinesh is passionate about the latest Java technologies and loves to write technical blogs related to it. He is a very active member of the Java and Spring community on different forums. When it comes to the Spring Framework and Java, Dinesh tops the list!

Share
Published by
Dinesh Rajput

Recent Posts

Strategy Design Patterns using Lambda

Strategy Design Patterns We can easily create a strategy design pattern using lambda. To implement…

2 years ago

Decorator Pattern using Lambda

Decorator Pattern A decorator pattern allows a user to add new functionality to an existing…

2 years ago

Delegating pattern using lambda

Delegating pattern In software engineering, the delegation pattern is an object-oriented design pattern that allows…

2 years ago

Spring Vs Django- Know The Difference Between The Two

Technology has emerged a lot in the last decade, and now we have artificial intelligence;…

2 years ago

TOP 20 MongoDB INTERVIEW QUESTIONS 2022

Managing a database is becoming increasingly complex now due to the vast amount of data…

2 years ago

Scheduler @Scheduled Annotation Spring Boot

Overview In this article, we will explore Spring Scheduler how we could use it by…

3 years ago