{"id":13342,"date":"2013-05-31T22:00:25","date_gmt":"2013-05-31T19:00:25","guid":{"rendered":"http:\/\/www.javacodegeeks.com\/?p=13342"},"modified":"2013-06-02T22:45:08","modified_gmt":"2013-06-02T19:45:08","slug":"spring-data-solr-tutorial-pagination","status":"publish","type":"post","link":"https:\/\/www.javacodegeeks.com\/2013\/05\/spring-data-solr-tutorial-pagination.html","title":{"rendered":"Spring Data Solr Tutorial: Pagination"},"content":{"rendered":"<p>In the earlier parts of my <a href=\"http:\/\/www.petrikainulainen.net\/spring-data-solr-tutorial\/\">Spring Data Solr tutorial<\/a>, we have implemented a simple search function which is used to search the information of todo entries. The current implementation of our search function shows all search results in a single page. This is not a viable solution for most real life applications because the number of search results can be so large that search function is no longer usable.<\/p>\n<p>This blog post provides us the solution to that problem by describing how we can paginate the query results or our search function with Spring Data Solr.<\/p>\n<p>This blog post is divided into five sections:<br \/>\n&nbsp;<\/p>\n<ul>\n<li>The first section describes how we can request the correct page manually and talks about the different return types of query methods.<\/li>\n<li>The second section describes how we can obtain the search result count by adding a custom method to our repository.<\/li>\n<li>The third section describes how we can paginate the search results of query methods.<\/li>\n<li>The fourth section teaches us to paginate the search results of dynamic queries.<\/li>\n<li>The fifth and last section describes how we can configure and use a technique called web pagination.<\/li>\n<\/ul>\n<p><strong>Note<\/strong>: These blog posts provides additional information which helps us to understand the concepts of described in this blog post:<\/p>\n<ul>\n<li><a href=\"http:\/\/www.javacodegeeks.com\/2013\/05\/running-solr-with-maven.html\">Running Solr with Maven<\/a><\/li>\n<li><a href=\"http:\/\/www.javacodegeeks.com\/2013\/05\/spring-data-solr-tutorial-introduction-to-solr.html\">Spring Data Solr Tutorial: Introduction to Solr<\/a><\/li>\n<li><a href=\"http:\/\/www.javacodegeeks.com\/2013\/05\/spring-data-solr-tutorial-configuration.html\">Spring Data Solr Tutorial: Configuration<\/a><\/li>\n<li><a href=\"http:\/\/www.javacodegeeks.com\/2013\/05\/spring-data-solr-tutorial-crud-almost.html\">Spring Data Solr Tutorial CRUD (Almost)<\/a><\/li>\n<li><a href=\"http:\/\/www.javacodegeeks.com\/2013\/05\/spring-data-solr-tutorial-adding-custom-methods-to-a-single-repository.html\">Spring Data Solr Tutorial: Adding Custom Methods to a Single Repository<\/a><\/li>\n<li><a href=\"http:\/\/www.javacodegeeks.com\/2013\/05\/spring-data-solr-tutorial-dynamic-queries.html\">Spring Data Solr Tutorial: Dynamic Queries<\/a><\/li>\n<li><a href=\"http:\/\/www.javacodegeeks.com\/2013\/05\/spring-data-solr-tutorial-sorting.html\">Spring Data Solr Tutorial: Sorting<\/a><\/li>\n<\/ul>\n<p>Let\u2019s get started.<\/p>\n<h2>Few Minutes of Theory<\/h2>\n<p>Before we will start making modifications to our example application, we will take a short look at the theory behind pagination. This section is divided in two subsections which are described in the following:<\/p>\n<ul>\n<li>The first section describes how we can specify the pagination options of our query.<\/li>\n<li>The second section describes the different return types of a query method.<\/li>\n<\/ul>\n<p>Let\u2019s move on.<\/p>\n<h4>Specifying the Wanted Page<\/h4>\n<p>The used pagination options are specified by using the <a href=\"http:\/\/static.springsource.org\/spring-data\/data-commons\/docs\/current\/api\/org\/springframework\/data\/domain\/PageRequest.html\" target=\"_blank\"><em>PageRequest<\/em><\/a> class which implements the <a href=\"http:\/\/static.springsource.org\/spring-data\/data-commons\/docs\/current\/api\/org\/springframework\/data\/domain\/Pageable.html\" target=\"_blank\"><em>Pageable<\/em><\/a> interface.<\/p>\n<p>The typical pagination requirements are given in the following:<\/p>\n<ul>\n<li>Get the query results belonging to a single page.<\/li>\n<li>Get the query results belonging to a single page when the query results are sorted by using the value of a single field.<\/li>\n<li>Get the query results belonging to a single page when the query results are sorted by using the values of multiple fields and the sort order of different fields is the same.<\/li>\n<li>Get the query results belonging to a single page when the query results are sorted by using the values of multiple fields and the sort order of different fields is not the same.<\/li>\n<\/ul>\n<p>Let\u2019s find out how we can create the <em>PageRequest<\/em> objects which fulfill the given requirements.<\/p>\n<p>First, we must create a <em>PageRequest<\/em> object which specifies that we want to get the query results belonging to a single page. We can create the <em>PageRequest<\/em> object by using the following code:<\/p>\n<pre class=\"brush:java\">\/\/Get the query results belonging to the first page when page size is 10.\r\nnew PageRequest(0, 10)<\/pre>\n<p>Second, we must create a <em>PageRequest<\/em> object which specifies that we want to get the results belonging to a single page when query results are sorted by using the value of a single field. We can create the <em>PageRequest<\/em> object by using the following code:<\/p>\n<pre class=\"brush:java\">\/Gets the query results belonging to the first page when page size is 10.\r\n\/\/Query results are sorted in descending order by using id field.\r\nnew PageRequest(0, 10 Sort.Direction.DESC, \"id\")<\/pre>\n<p>Third, we must create a <em>PageRequest<\/em> object which specifies that we want to get the results belonging to a single page when the query results are sorted by using multiple fields and the sort order of different fields is same. We can create the <em>PageRequest<\/em> object by using the following code:<\/p>\n<pre class=\"brush:java\">\/\/Gets the query results belonging to the first page when page size is 10.\r\n\/\/Query results are sorted in descending order by using id and description fields.\r\nnew PageRequest(0, 10 Sort.Direction.DESC, \"id\", \"description\")<\/pre>\n<p>Fourth, we must create a <em>PageRequest<\/em> object which specifies that want to get 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. We can create this object by using the following code:<\/p>\n<pre class=\"brush:java\">\/\/Gets the query results belonging to the first page when page size is 10.\r\n\/\/Query results are sorted in descending order order by using the description field\r\n\/\/and in ascending order by using the id field.\r\nSort sort = new Sort(Sort.Direction.DESC, \"description\").and(new Sort(Sort.Direction.ASC, \"id\"))\r\nnew PageRequest(0, 10, sort);<\/pre>\n<p>We now know how we can create new <em>PageRequest<\/em> objects. Let\u2019s move on and talk about the different return types of query methods.<\/p>\n<h4>Deciding the Return Type of a Query Method<\/h4>\n<p>When a query method uses pagination, it can have two return types. These return types are described in the following (We will assume that the name of our model class is <em>TodoDocument<\/em>):<\/p>\n<ul>\n<li>When we are interested about the pagination metadata, the return type of our query method must be <em>Page&lt;TodoDocument&gt;<\/em> (Get more information about the <a href=\"http:\/\/static.springsource.org\/spring-data\/data-commons\/docs\/current\/api\/org\/springframework\/data\/domain\/Page.html\" target=\"_blank\"><em>Page<\/em><\/a> interface which declares the methods used to obtain the pagination metadata).<\/li>\n<li>When we are not interested about the pagination metadata, the return type of our query method should be <em>List&lt;TodoDocument&gt;<\/em>.<\/li>\n<\/ul>\n<h2>Getting the Search Result Count<\/h2>\n<p>Before we can start paginating the search results of our queries, we have to implement a function which is used to get the number of todo entries which matches with given search criteria. This number is required so that we can implement the pagination logic to the frontend.<\/p>\n<p>We can implement this function by following these steps:<\/p>\n<ol>\n<li>Add a custom method to our repository. This method is used to return the search result count.<\/li>\n<li>Create a new service method which uses our custom repository method.<\/li>\n<\/ol>\n<p>These steps are described with more details in the following subsections.<\/p>\n<h4>Adding a Custom Method to Our Repository<\/h4>\n<p>At the moment it is not possible to create a count query without <a href=\"http:\/\/www.javacodegeeks.com\/2013\/05\/spring-data-solr-tutorial-adding-custom-methods-to-a-single-repository.html\">adding a custom method to a repository<\/a>. We can do this by following these steps:<\/p>\n<ol>\n<li>Create a custom repository interface.<\/li>\n<li>Implement the custom repository interface.<\/li>\n<li>Modify the actual repository interface.<\/li>\n<\/ol>\n<p>Let\u2019s move on and find out how this is done.<\/p>\n<h2>Creating a Custom Repository Interface<\/h2>\n<p>We can create a custom repository interface by following these steps:<\/p>\n<ol>\n<li>Create an interface called <em>CustomTodoDocumentRepository<\/em>.<\/li>\n<li>Add a <em>count()<\/em> method to the created interface. This method takes the used search term as a method parameter.<\/li>\n<\/ol>\n<p>The source code of the <em>CustomTodoDocumentRepository<\/em> interface looks as follows:<\/p>\n<pre class=\"brush:java\">public interface CustomTodoDocumentRepository {\r\n\r\n    public long count(String searchTerm);\r\n\r\n    \/\/Other methods are omitted\r\n}<\/pre>\n<h2>Implementing the Custom Repository Interface<\/h2>\n<p>We can implement the custom repository interface by following these steps:<\/p>\n<ol>\n<li>Create a class called <em>TodoDocumentRepositoryImpl<\/em> and implement the <em>CustomTodoDocumentRepository<\/em> interface.<\/li>\n<li>Annotate the class with the <em>@Repository<\/em> annotation.<\/li>\n<li>Add <em>SolrTemplate<\/em> field to the class and annotate the field with the <em>@Resource<\/em> annotation.<\/li>\n<li>Implement the <em>count()<\/em> method.<\/li>\n<\/ol>\n<p>Let\u2019s take a closer look at the implementation of the <em>count()<\/em> method. We can implement this method by following these steps:<\/p>\n<ol>\n<li>Get words of the given search term.<\/li>\n<li>Construct the used search criteria by calling the private <em>constructSearchConditions()<\/em> method and pass the words of the search term as a method parameter.<\/li>\n<li>Create the executed query by creating a new <em>SimpleQuery<\/em> object and pass the created <em>Criteria<\/em> object as a constructor parameter.<\/li>\n<li>Get the search result count by calling the <em>count()<\/em> method of the <em>SolrTemplate<\/em> class and pass the created <em>SimpleQuery<\/em> object as a method parameter.<\/li>\n<li>Return the search result count.<\/li>\n<\/ol>\n<p>The source code of the <em>TodoDocumentRepositoryImpl<\/em> class looks as follows:<\/p>\n<pre class=\"brush:java\">import org.springframework.data.solr.core.SolrTemplate;\r\nimport org.springframework.data.solr.core.query.Criteria;\r\nimport org.springframework.data.solr.core.query.SimpleQuery;\r\nimport org.springframework.stereotype.Repository;\r\n\r\nimport javax.annotation.Resource;\r\n\r\n@Repository\r\npublic class TodoDocumentRepositoryImpl implements CustomTodoDocumentRepository {\r\n\r\n    @Resource\r\n    private SolrTemplate solrTemplate;\r\n\r\n    @Override\r\n    public long count(String searchTerm) {\r\n        String[] words = searchTerm.split(\" \");\r\n        Criteria conditions = createSearchConditions(words);\r\n        SimpleQuery countQuery = new SimpleQuery(conditions);\r\n\r\n        return solrTemplate.count(countQuery);\r\n    }\r\n\r\n    private Criteria createSearchConditions(String[] words) {\r\n        Criteria conditions = null;\r\n\r\n        for (String word: words) {\r\n            if (conditions == null) {\r\n                conditions = new Criteria(\"title\").contains(word)\r\n                        .or(new Criteria(\"description\").contains(word));\r\n            }\r\n            else {\r\n                conditions = conditions.or(new Criteria(\"title\").contains(word))\r\n                        .or(new Criteria(\"description\").contains(word));\r\n            }\r\n        }\r\n\r\n        return conditions;\r\n    }\r\n\r\n    \/\/Other methods are omitted.\r\n}<\/pre>\n<h2>Modifying the Actual Repository Interface<\/h2>\n<p>We can make the custom <em>count()<\/em> method visible to the users of our repository by extending the <em>CustomTodoRepositoryInterface<\/em>. The source code of the <em>TodoDocumentRepository<\/em> looks as follows:<div style=\"display:inline-block; margin: 15px 0;\"> <div id=\"adngin-JavaCodeGeeks_incontent_video-0\" style=\"display:inline-block;\"><\/div> <\/div><\/p>\n<pre class=\"brush:java\">public interface TodoDocumentRepository extends CustomTodoRepository, SolrCrudRepository&lt;TodoDocument, String&gt; {\r\n    \/\/Repository methods are omitted.\r\n}<\/pre>\n<h4>Using the Custom Repository Method<\/h4>\n<p>We can use the created repository method by following these steps:<\/p>\n<ol>\n<li>Modify the <em>TodoIndexService<\/em> interface.<\/li>\n<li>Implement the modified interface.<\/li>\n<\/ol>\n<p>These steps are described with more details in the following.<\/p>\n<p><strong>Note<\/strong>: We have to make other changes as well but I will not describe these changes here since they are not related to Spring Data Solr.<\/p>\n<h2>Modifying the Service Interface<\/h2>\n<p>We have to modify the <em>TodoIndexService<\/em> interface by adding a new <em>countSearchResults()<\/em> method to it. This method takes the used search term as a method parameter and returns the search result count. The source code of the <em>TodoIndexService<\/em> interface looks as follows:<\/p>\n<pre class=\"brush:java\">public interface TodoIndexService {\r\n\r\n    public long countSearchResults(String searchTerm);\r\n\r\n    \/\/Other methods are omitted.\r\n}<\/pre>\n<h2>Implementing the Modified Interface<\/h2>\n<p>We can implement the <em>countSearchResults()<\/em> method by following these steps:<\/p>\n<ol>\n<li>Add the <em>countSearchResults()<\/em> method to the <em>RepositoryTodoIndexService<\/em> class.<\/li>\n<li>Obtain the search result count by calling the custom repository method and return the search result count.<\/li>\n<\/ol>\n<p>The relevant part of the <em>RepositoryTodoIndexService<\/em> class looks as follows:<\/p>\n<pre class=\"brush:java\">import org.springframework.stereotype.Service;\r\nimport org.springframework.transaction.annotation.Transactional;\r\n\r\nimport javax.annotation.Resource;\r\nimport java.util.ArrayList;\r\nimport java.util.List;\r\n\r\n@Service\r\npublic class RepositoryTodoIndexService implements TodoIndexService {\r\n\r\n    @Resource\r\n    private TodoDocumentRepository repository;\r\n\r\n    @Override\r\n    public long countSearchResults(String searchTerm) {\r\n        return repository.count(searchTerm);\r\n    }\r\n\r\n    \/\/Other methods are omitted.\r\n}<\/pre>\n<h2>Paginate the Query Results of Query Methods<\/h2>\n<p>When we are creating our queries by using query methods, we can paginate the query results by following these steps:<\/p>\n<ol>\n<li>Add a new <em>Pageable<\/em> parameter to the query method. This parameter specifies the details of the fetched page.<\/li>\n<li>Modify the service layer by adding a new <em>Pageable<\/em> parameter to the <em>search()<\/em> method of the <em>TodoIndexService<\/em> interface.<\/li>\n<\/ol>\n<p>Let\u2019s get started.<\/p>\n<h4>Modifying the Repository Interface<\/h4>\n<p>We can add pagination support to our repository by adding a <em>Pageable<\/em> parameter to the query method which is used to build the executed query. Let\u2019s take a look at the declarations of our query methods.<\/p>\n<h2>Query Generation from Method Name<\/h2>\n<p>When the executed query is created by using the query generation from method name strategy, we have to add a <em>Pageable<\/em> parameter to the <em>findByTitleContainsOrDescriptionContains()<\/em> method of the <em>TodoDocumentRepository<\/em> interface. These source code of our repository interface looks as follows:<\/p>\n<pre class=\"brush:java\">import org.springframework.data.domain.Pageable;\r\nimport org.springframework.data.solr.repository.SolrCrudRepository;\r\n\r\nimport java.util.List;\r\n\r\npublic interface TodoDocumentRepository extends CustomTodoDocumentRepository, SolrCrudRepository&lt;TodoDocument, String&gt; {\r\n\r\n    public List&lt;TodoDocument&gt; findByTitleContainsOrDescriptionContains(String title, String description, Pageable page);\r\n}<\/pre>\n<h2>Named Queries<\/h2>\n<p>When are using named queries, we have to add a <em>Pageable<\/em> parameter to the <em>findByNamedQuery()<\/em> method of the <em>TodoDocumentRepository<\/em> interface. The source code of the <em>TodoDocumentRepository<\/em> interface looks as follows:<\/p>\n<pre class=\"brush:java\">import org.springframework.data.domain.Pageable;\r\nimport org.springframework.data.solr.repository.Query;\r\nimport org.springframework.data.solr.repository.SolrCrudRepository;\r\n\r\nimport java.util.List;\r\n\r\npublic interface TodoDocumentRepository extends CustomTodoDocumentRepository, SolrCrudRepository&lt;TodoDocument, String&gt; {\r\n\r\n    @Query(name = \"TodoDocument.findByNamedQuery\")\r\n    public List&lt;TodoDocument&gt; findByNamedQuery(String searchTerm, Pageable page);\r\n}<\/pre>\n<h2>@Query Annotation<\/h2>\n<p>When the executed query is created by using the <em>@Query<\/em> annotation, we have to add a <em>Pageable<\/em> parameter to the <em>findByQueryAnnotation()<\/em> method of the <em>TodoDocumentRepository<\/em> interface. The source code of our repository interface looks as follows:<\/p>\n<pre class=\"brush:java\">import org.springframework.data.domain.Pageable;\r\nimport org.springframework.data.solr.repository.Query;\r\nimport org.springframework.data.solr.repository.SolrCrudRepository;\r\n\r\nimport java.util.List;\r\n\r\npublic interface TodoDocumentRepository extends CustomTodoDocumentRepository, SolrCrudRepository&lt;TodoDocument, String&gt; {\r\n\r\n    @Query(\"title:*?0* OR description:*?0*\")\r\n    public List&lt;TodoDocument&gt; findByQueryAnnotation(String searchTerm, Pageable page);\r\n}<\/pre>\n<h4>Modifying the Service Layer<\/h4>\n<p>We have to the following modifications to the service layer of our example application:<\/p>\n<ol>\n<li>Add a Pageable parameter to the <em>search()<\/em> method of the <em>TodoIndexService<\/em> interface.<\/li>\n<li>Implement the new search() method.<\/li>\n<\/ol>\n<p><strong>Note<\/strong>: We have to make other changes as well but I will not describe these changes here since they are not related to Spring Data Solr.<\/p>\n<p>The source code of the <em>TodoIndexService<\/em> interface looks as follows:<\/p>\n<pre class=\"brush:java\">import org.springframework.data.domain.Pageable;\r\nimport java.util.List;\r\n\r\npublic interface TodoIndexService {\r\n\r\n    public List&lt;TodoDocument&gt; search(String searchTerm, Pageable page);\r\n\r\n    \/\/Other methods are omitted.\r\n}<\/pre>\n<p>We can use the modified query methods by making the following changes to the <em>search()<\/em> method of the <em>RepositoryIndexService<\/em> class:<\/p>\n<ol>\n<li>Get the paginated query results by calling the query method of our repository and pass the used search term and the <em>Pageable<\/em> object as method parameters.<\/li>\n<li>Return the query results.<\/li>\n<\/ol>\n<p>Let\u2019s move and take a look at different implementations of the <em>search()<\/em> method.<\/p>\n<h2>Query Generation from Method Name<\/h2>\n<p>When we are building our queries by using the query generation from method name strategy, we can get query results belonging to a specific page by using the <em>findByTitleContainsOrDescriptionContains()<\/em> method of the <em>TodoDocumentRepository<\/em> interface.<\/p>\n<p>The relevant part of the <em>RepositoryTodoIndexService<\/em> class looks as follows:<\/p>\n<pre class=\"brush:java\">import org.springframework.beans.factory.annotation.Value;\r\nimport org.springframework.data.domain.Pageable;\r\nimport org.springframework.data.domain.Sort;\r\nimport org.springframework.stereotype.Service;\r\nimport org.springframework.transaction.annotation.Transactional;\r\n\r\nimport javax.annotation.Resource;\r\nimport java.util.ArrayList;\r\nimport java.util.List;\r\n\r\n@Service\r\npublic class RepositoryTodoIndexService implements TodoIndexService {\r\n\r\n    @Resource\r\n    private TodoDocumentRepository repository;\r\n\r\n    @Override\r\n    public List&lt;TodoDocument&gt; search(String searchTerm, Pageable page) {\r\n        return repository.findByTitleContainsOrDescriptionContains(searchTerm, searchTerm, page);\r\n    }\r\n   \r\n    \/\/Other methods are omitted\r\n}<\/pre>\n<h2>Named Queries<\/h2>\n<p>When we are using named query for building the executed query, we can get the search results belonging to a specific page by using the <em>findByNamedQuery()<\/em> method of the <em>TodoDocumentRepository<\/em> interface.<\/p>\n<p>The relevant part of the <em>RepositoryTodoIndexService<\/em> class looks as follows:<\/p>\n<pre class=\"brush:java\">import org.springframework.beans.factory.annotation.Value;\r\nimport org.springframework.data.domain.Pageable;\r\nimport org.springframework.data.domain.Sort;\r\nimport org.springframework.stereotype.Service;\r\nimport org.springframework.transaction.annotation.Transactional;\r\n\r\nimport javax.annotation.Resource;\r\nimport java.util.ArrayList;\r\nimport java.util.List;\r\n\r\n@Service\r\npublic class RepositoryTodoIndexService implements TodoIndexService {\r\n\r\n    @Resource\r\n    private TodoDocumentRepository repository;\r\n\r\n    @Override\r\n    public List&lt;TodoDocument&gt; search(String searchTerm, Pageable page) {\r\n        return repository.findByNamedQuery(searchTerm, page);\r\n    }\r\n   \r\n    \/\/Other methods are omitted\r\n}<\/pre>\n<h2>@Query Annotation<\/h2>\n<p>When we are building our query by using the <em>@Query<\/em> annotation, we can get the search results which belongs to a specific page by calling the <em>findByQueryAnnotation()<\/em> method of the <em>TodoDocumentRepository<\/em> interface.<\/p>\n<p>The source code of the <em>RepositoryTodoIndexService<\/em> class looks as follows:<\/p>\n<pre class=\"brush:java\">import org.springframework.beans.factory.annotation.Value;\r\nimport org.springframework.data.domain.Pageable;\r\nimport org.springframework.data.domain.Sort;\r\nimport org.springframework.stereotype.Service;\r\nimport org.springframework.transaction.annotation.Transactional;\r\n\r\nimport javax.annotation.Resource;\r\nimport java.util.ArrayList;\r\nimport java.util.List;\r\n\r\n@Service\r\npublic class RepositoryTodoIndexService implements TodoIndexService {\r\n\r\n    @Resource\r\n    private TodoDocumentRepository repository;\r\n\r\n    @Override\r\n    public List&lt;TodoDocument&gt; search(String searchTerm, Pageable page) {\r\n        return repository.findByQueryAnnotation(searchTerm, page);\r\n    }\r\n   \r\n    \/\/Other methods are omitted\r\n}<\/pre>\n<h2>Paginating the Query Results of Dynamic Queries<\/h2>\n<p>We can paginate the query results of dynamic queries by following these steps:<\/p>\n<ol>\n<li>Add a Pageable parameter to the <em>search()<\/em> method of our custom repository.<\/li>\n<li>Modify the service layer by adding a <em>Pageable<\/em> parameter to the search() method of the <em>TodoIndexService<\/em> interface.<\/li>\n<\/ol>\n<p>These steps are described with more details in the following subsections.<\/p>\n<h4>Changing the Custom Repository<\/h4>\n<p>We have to add pagination support to our custom repository. We can do this by following these steps:<\/p>\n<ol>\n<li>Modify the custom repository interface by adding a <em>Pageable<\/em> parameter to its <em>search()<\/em> method.<\/li>\n<li>Change the implementation of the <em>search()<\/em> method by adding pagination support to it.<\/li>\n<\/ol>\n<p>Let\u2019s move on and find out how this is done.<\/p>\n<h2>Changing the Custom Repository Interface<\/h2>\n<p>We have to add a <em>Pageable<\/em> parameter to the <em>search()<\/em> method declared in the <em>CustomTodoDocumentRepository<\/em> interface. The source code of our custom repository interface looks as follows:<\/p>\n<pre class=\"brush:java\">import org.springframework.data.domain.Pageable;\r\n\r\nimport java.util.List;\r\n\r\npublic interface CustomTodoDocumentRepository {\r\n\r\n    public List&lt;TodoDocument&gt; search(String searchTerm, Pageable page);\r\n\r\n    \/\/Other methods are omitted.\r\n}<\/pre>\n<h2>Implementing the Custom Repository Method<\/h2>\n<p>Our next step is to add pagination support to the implementation of the <em>search()<\/em> method. We can implement the <em>search()<\/em> method of the <em>TodoDocumentRepositoryImpl<\/em> class by following these steps:<\/p>\n<ol>\n<li>Get the words of the search term.<\/li>\n<li>Construct the used search criteria by calling the private <em>createSearchConditions()<\/em> method and passing the words of the search term as a method parameter.<\/li>\n<li>Create the executed query by creating a new <em>SimpleQuery<\/em> object and pass the created <em>Criteria<\/em> object as a constructor parameter.<\/li>\n<li>Set the pagination options of the query by calling the <em>setPageRequest()<\/em> method of the <em>SimpleQuery<\/em> class. Pass the <em>Pageable<\/em> object as a method parameter.<\/li>\n<li>Get the search results by calling the <em>queryForPage()<\/em> method of the <em>SolrTemplate<\/em> class. Pass the created query and the type of the expected return objects as method parameters.<\/li>\n<li>Return the search results by calling the <em>getContent()<\/em> method of the <em>Page<\/em> interface.<\/li>\n<\/ol>\n<p>The source code of the <em>TodoDocumentRepositoryImpl<\/em> class looks as follows:<\/p>\n<pre class=\"brush:java\">import org.springframework.data.domain.Page;\r\nimport org.springframework.data.domain.Pageable;\r\nimport org.springframework.data.solr.core.SolrTemplate;\r\nimport org.springframework.data.solr.core.query.Criteria;\r\nimport org.springframework.data.solr.core.query.SimpleQuery;\r\nimport org.springframework.stereotype.Repository;\r\n\r\nimport javax.annotation.Resource;\r\nimport java.util.ArrayList;\r\nimport java.util.List;\r\n\r\n@Repository\r\npublic class TodoDocumentRepositoryImpl implements CustomTodoDocumentRepository {\r\n\r\n    @Resource\r\n    private SolrTemplate solrTemplate;\r\n\r\n    @Override\r\n    public List&lt;TodoDocument&gt; search(String searchTerm, Pageable page) {\r\n        String[] words = searchTerm.split(\" \");\r\n\r\n        Criteria conditions = createSearchConditions(words);\r\n        SimpleQuery search = new SimpleQuery(conditions);\r\n        search.setPageRequest(page);\r\n\r\n        Page results = solrTemplate.queryForPage(search, TodoDocument.class);\r\n        return results.getContent();\r\n    }\r\n\r\n    private Criteria createSearchConditions(String[] words) {\r\n        Criteria conditions = null;\r\n\r\n        for (String word: words) {\r\n            if (conditions == null) {\r\n                conditions = new Criteria(\"title\").contains(word)\r\n                        .or(new Criteria(\"description\").contains(word));\r\n            }\r\n            else {\r\n                conditions = conditions.or(new Criteria(\"title\").contains(word))\r\n                        .or(new Criteria(\"description\").contains(word));\r\n            }\r\n        }\r\n\r\n        return conditions;\r\n    }\r\n\r\n    \/\/Other methods are omitted.\r\n}<\/pre>\n<h4>Using the Custom Repository<\/h4>\n<p>Before we can use the modified repository method, we have to make the following changes to the service layer of our example application:<\/p>\n<ol>\n<li>Add a <em>Pageable<\/em> parameter to the <em>search()<\/em> method of the <em>TodoIndexService<\/em> interface.<\/li>\n<li>Implement the <em>search()<\/em> method.<\/li>\n<\/ol>\n<p>These steps are described with more details in following.<\/p>\n<p><strong>Note<\/strong>: We have to make other changes as well but I will not describe these changes here since they are not related to Spring Data Solr.<\/p>\n<h2>Modifying the Service Interface<\/h2>\n<p>We have to add a <em>Pageable<\/em> parameter to the <em>search()<\/em> method of the <em>TodoIndexService<\/em> interface. The source code of the <em>TodoIndexService<\/em> looks as follows:<\/p>\n<pre class=\"brush:java\">import org.springframework.data.domain.Pageable;\r\nimport java.util.List;\r\n\r\npublic interface TodoIndexService {\r\n\r\n    public List&lt;TodoDocument&gt; search(String searchTerm, Pageable page);\r\n\r\n    \/\/Other methods are omitted.\r\n}<\/pre>\n<h2>Implementing the Service Interface<\/h2>\n<p>When we are building our by using the criteria API of Spring Data Solr, we can get the query results by calling the <em>search()<\/em> method of our custom repository and passing the user search term and the <em>Pageable<\/em> object as method parameters.<\/p>\n<p>The source code of the <em>RepositoryTodoIndexService<\/em> class looks as follows:<\/p>\n<pre class=\"brush:java\">import org.springframework.data.domain.Pageable;\r\nimport org.springframework.stereotype.Service;\r\nimport javax.annotation.Resource;\r\nimport java.util.List;\r\n\r\n@Service\r\npublic class RepositoryTodoIndexService implements TodoIndexService {\r\n\r\n    @Resource\r\n    private TodoDocumentRepository repository;\r\n\r\n    @Override\r\n    public List&lt;TodoDocument&gt; search(String searchTerm, Pageable page) {\r\n        return repository.search(searchTerm, page);\r\n    }\r\n\r\n    \/\/Other methods are omitted.\r\n}<\/pre>\n<h2>Using Web Pagination<\/h2>\n<p>One question is still left unanswered. That is question is:<\/p>\n<p>Where the pagination options used to paginate the query results of our queries are specified?<\/p>\n<p>We will create the pagination options of our queries by using a technique called <a href=\"http:\/\/static.springsource.org\/spring-data\/data-solr\/docs\/1.0.0.RC1\/reference\/htmlsingle\/#web-pagination\" target=\"_blank\">web pagination<\/a>. This technique is based on a custom argument resolver class called <em>PageableArgumentResolver<\/em>. This class parses pagination information from HTTP request and makes it possible to add a <em>Pageable<\/em> method parameter to controller methods.<\/p>\n<p>This section describes how we can configure and use this technique in our example application. It is divided into three subsections:<\/p>\n<ul>\n<li>The first subsection describes how we can configure the <em>PageableArgumentResolver<\/em> class.<\/li>\n<li>The second subsection describes how we can use it.<\/li>\n<li>The last subsection talks about the pros and cons of web pagination.<\/li>\n<\/ul>\n<p>Let\u2019s find out how we can use this technique in our example application.<\/p>\n<h4>Configuration<\/h4>\n<p>This subsection describes how we can configure the <em>PageableArgumentResolver<\/em> class which is to used extract pagination options from HTTP requests. Let\u2019s find out how we do this by using Java configuration and XML configuration.<\/p>\n<h2>Java Configuration<\/h2>\n<p>We can add a custom argument argument resolver by making the following changes to the <em>ExampleApplicationContext<\/em> class:<\/p>\n<ol>\n<li>Override the <em>addArgumentResolvers()<\/em> method of the <em>WebMvcConfigurerAdapter<\/em> class.<\/li>\n<li>Implement the <em>addArgumentResolvers()<\/em> method by creating new <em>PageableArgumentResolver<\/em> object and adding the created object to the list of argument resolvers which is given as a method parameter.<\/li>\n<\/ol>\n<p>The relevant part of the <em>ExampleApplicationContext<\/em> class looks as follows:<\/p>\n<pre class=\"brush:java\">import org.springframework.data.web.PageableArgumentResolver;\r\nimport org.springframework.web.method.support.HandlerMethodArgumentResolver;\r\nimport org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;\r\nimport org.springframework.web.servlet.mvc.method.annotation.ServletWebArgumentResolverAdapter;\r\n\r\nimport java.util.List;\r\n\r\n\/\/Annotations are omitted.\r\npublic class ExampleApplicationContext extends WebMvcConfigurerAdapter {\r\n\r\n    @Override\r\n    public void addArgumentResolvers(List&lt;HandlerMethodArgumentResolver&gt; argumentResolvers) {\r\n        PageableArgumentResolver pageableArgumentResolver = new PageableArgumentResolver();\r\n        argumentResolvers.add(new ServletWebArgumentResolverAdapter(pageableArgumentResolver));\r\n    }\r\n\r\n    \/\/Other methods are omitted.\r\n}<\/pre>\n<h2>XML Configuration<\/h2>\n<p>We can configure a custom argument resolver by making the following changes to the <em>exampleApplicationContext.xml<\/em> file:<\/p>\n<ol>\n<li>Use the <em>argument-resolvers<\/em> element of the <em>mvc<\/em> namespace for configuring the custom argument resolvers.<\/li>\n<li>Configure the <em>PageableArgumentResolver<\/em> bean inside the <em>argument-resolvers<\/em> element.<\/li>\n<\/ol>\n<p>The relevant part of the <em>exampleApplicationContext.xml<\/em> file looks as follows:<\/p>\n<pre class=\"brush:xml\">&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;\r\n&lt;beans xmlns=\"http:\/\/www.springframework.org\/schema\/beans\"\r\n      xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"\r\n      xmlns:mvc=\"http:\/\/www.springframework.org\/schema\/mvc\"\r\n      xmlns:context=\"http:\/\/www.springframework.org\/schema\/context\"\r\n      xsi:schemaLocation=\"http:\/\/www.springframework.org\/schema\/beans http:\/\/www.springframework.org\/schema\/beans\/spring-beans.xsd\r\n      http:\/\/www.springframework.org\/schema\/mvc http:\/\/www.springframework.org\/schema\/mvc\/spring-mvc-3.2.xsd\"&gt;\r\n    &lt;mvc:annotation-driven&gt;\r\n        &lt;mvc:argument-resolvers&gt;\r\n            &lt;bean id=\"pageagleArgumentResolver\" class=\"org.springframework.data.web.PageableArgumentResolver\"\/&gt;\r\n        &lt;\/mvc:argument-resolvers&gt;\r\n    &lt;\/mvc:annotation-driven&gt;\r\n\r\n    &lt;!-- Configuration is omitted. --&gt;\r\n&lt;\/beans&gt;<\/pre>\n<h4>Usage<\/h4>\n<p>After we have configured the <em>PageableArgumentResolver<\/em> class by using one of methods which were described earlier, we can add <em>Pageable<\/em> method parameters to our controller methods. The <em>search()<\/em> method the <em>TodoController<\/em> class is a good example of this. The relevant part of its source code looks as follows:<\/p>\n<pre class=\"brush:java\">import org.springframework.data.domain.Pageable;\r\nimport org.springframework.stereotype.Controller;\r\nimport org.springframework.web.bind.annotation.*;\r\n\r\nimport javax.annotation.Resource;\r\nimport java.util.List;\r\n\r\n@Controller\r\npublic class TodoController {\r\n\r\n    \/\/Fields are omitted.\r\n\r\n    @RequestMapping(value = \"\/api\/todo\/search\/{searchTerm}\", method = RequestMethod.GET)\r\n    @ResponseBody\r\n    public List&lt;TodoDTO&gt; search(@PathVariable(\"searchTerm\") String searchTerm, Pageable page) {\r\n        \/\/Implementation is omitted.\r\n    }\r\n\r\n    \/\/Other methods are omitted.\r\n}<\/pre>\n<p>However, adding the <em>Pageable<\/em> argument to the controller method is not enough. We still have to add the pagination options to the HTTP request. This is done by adding special request parameters to the request. These request parameters are described in the following:<\/p>\n<ul>\n<li>The <em>page.page<\/em> request parameter specifies the requested page.<\/li>\n<li>The <em>page.size<\/em> request parameter specifies the page size.<\/li>\n<li>The <em>page.sort<\/em> request parameter specifies the property which is used to sort the query results.<\/li>\n<li>The <em>page.sort.dir<\/em> request parameter specifies the sort order.<\/li>\n<\/ul>\n<p>Let\u2019s spend a moment and think about the pros and cons of web pagination.<\/p>\n<h4>Pros and Cons<\/h4>\n<p>The web pagination has both pros and cons which we should be aware of before making the decision to use it in our applications. Let\u2019s find out what these are.<\/p>\n<h2>Pros<\/h2>\n<p>Using web pagination has one major benefit:<\/p>\n<p>It is an easy and simple to transfer pagination options from the web layer to the repository layer. All we have to do is to configure a custom argument resolver, add a <em>Pageable<\/em> parameter to a controller method and send the pagination options by using specific request parameters. This is a lot simpler than processing pagination options in our code and manually creating a <em>PageRequest<\/em> object.<\/p>\n<h2>Cons<\/h2>\n<p>The cons of using web pagination are described in the following:<\/p>\n<ul>\n<li>Web pagination creates a dependency between the web layer and Spring Data. This means that the implementation details of the repository layer leaks into to the upper layers of our application. Although purists will probably claim that this is huge mistake, I don\u2019t share their opinion. I think that abstractions should make our life easier, not harder. We must also remember that <a href=\"http:\/\/www.joelonsoftware.com\/articles\/LeakyAbstractions.html\" target=\"_blank\">the law of leaky abstractions<\/a> states that all-non trivial abstractions, to some degree, are leaky.<\/li>\n<li>One real disadvantage of web pagination is that we can use it only if our search results are sorted by using a single field. Although this is perfectly fine for most use cases, there are situations when this becomes a problem. If this happens, we have to process pagination options manually.<\/li>\n<\/ul>\n<h2>Summary<\/h2>\n<p>We have now added the pagination of search results to our example application. This tutorial has taught us the following things:<\/p>\n<ul>\n<li>We learned to create new <em>PageRequest<\/em> objects.<\/li>\n<li>We learned that we can select the return type of our query method from two different options.<\/li>\n<li>We learned to paginate the query results of query methods and dynamic queries.<\/li>\n<li>We know how we can use web pagination, and we are aware of its pros and cons.<\/li>\n<\/ul>\n<p>The next part of my Spring Data Solr Tutorial describes how we can add custom methods to all Spring Data Solr repositories.<\/p>\n<p>P.S. The example applications of this blog post are available at Github (<a href=\"https:\/\/github.com\/pkainulainen\/spring-data-solr-examples\/tree\/master\/query-methods-pagination\" target=\"_blank\">query methods<\/a> and <a href=\"https:\/\/github.com\/pkainulainen\/spring-data-solr-examples\/tree\/master\/criteria-pagination\" target=\"_blank\">dynamic queries<\/a>).<br \/>\n&nbsp;<\/p>\n<div style=\"border: 1px solid #D8D8D8; background: #FAFAFA; width: 100%; padding-left: 5px;\"><b><i>Reference: <\/i><\/b><a href=\"http:\/\/www.javacodegeeks.com\/2013\/05\/spring-data-solr-tutorial-pagination.html\">Spring Data Solr Tutorial: Pagination<\/a> from our <a href=\"http:\/\/www.javacodegeeks.com\/jcg\">JCG partner<\/a> Petri Kainulainen at the <a href=\"http:\/\/www.petrikainulainen.net\/\">Petri Kainulainen<\/a> blog.<\/div>\n","protected":false},"excerpt":{"rendered":"<p>In the earlier parts of my Spring Data Solr tutorial, we have implemented a simple search function which is used to search the information of todo entries. The current implementation of our search function shows all search results in a single page. This is not a viable solution for most real life applications because the &hellip;<\/p>\n","protected":false},"author":429,"featured_media":80,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[470,30,321],"class_list":["post-13342","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-enterprise-java","tag-apache-solr","tag-spring","tag-spring-data"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Spring Data Solr Tutorial: Pagination<\/title>\n<meta name=\"description\" content=\"In the earlier parts of my Spring Data Solr tutorial, we have implemented a simple search function which is used to search the information of todo\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.javacodegeeks.com\/2013\/05\/spring-data-solr-tutorial-pagination.html\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Spring Data Solr Tutorial: Pagination\" \/>\n<meta property=\"og:description\" content=\"In the earlier parts of my Spring Data Solr tutorial, we have implemented a simple search function which is used to search the information of todo\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.javacodegeeks.com\/2013\/05\/spring-data-solr-tutorial-pagination.html\" \/>\n<meta property=\"og:site_name\" content=\"Java Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/javacodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2013-05-31T19:00:25+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2013-06-02T19:45:08+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/apache-solr-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Petri Kainulainen\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@https:\/\/twitter.com\/petrikainulaine\" \/>\n<meta name=\"twitter:site\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Petri Kainulainen\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"22 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/05\\\/spring-data-solr-tutorial-pagination.html#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/05\\\/spring-data-solr-tutorial-pagination.html\"},\"author\":{\"name\":\"Petri Kainulainen\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/5af4df3fdfeb79e9fa3598d79bff2c9e\"},\"headline\":\"Spring Data Solr Tutorial: Pagination\",\"datePublished\":\"2013-05-31T19:00:25+00:00\",\"dateModified\":\"2013-06-02T19:45:08+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/05\\\/spring-data-solr-tutorial-pagination.html\"},\"wordCount\":3137,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/05\\\/spring-data-solr-tutorial-pagination.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/apache-solr-logo.jpg\",\"keywords\":[\"Apache Solr\",\"Spring\",\"Spring Data\"],\"articleSection\":[\"Enterprise Java\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/05\\\/spring-data-solr-tutorial-pagination.html#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/05\\\/spring-data-solr-tutorial-pagination.html\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/05\\\/spring-data-solr-tutorial-pagination.html\",\"name\":\"Spring Data Solr Tutorial: Pagination\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/05\\\/spring-data-solr-tutorial-pagination.html#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/05\\\/spring-data-solr-tutorial-pagination.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/apache-solr-logo.jpg\",\"datePublished\":\"2013-05-31T19:00:25+00:00\",\"dateModified\":\"2013-06-02T19:45:08+00:00\",\"description\":\"In the earlier parts of my Spring Data Solr tutorial, we have implemented a simple search function which is used to search the information of todo\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/05\\\/spring-data-solr-tutorial-pagination.html#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/05\\\/spring-data-solr-tutorial-pagination.html\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/05\\\/spring-data-solr-tutorial-pagination.html#primaryimage\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/apache-solr-logo.jpg\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/apache-solr-logo.jpg\",\"width\":150,\"height\":150},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/05\\\/spring-data-solr-tutorial-pagination.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Enterprise Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\\\/enterprise-java\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"Spring Data Solr Tutorial: Pagination\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"name\":\"Java Code Geeks\",\"description\":\"Java Developers Resource Center\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"alternateName\":\"JCG\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.javacodegeeks.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/javacodegeeks\",\"https:\\\/\\\/x.com\\\/javacodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/5af4df3fdfeb79e9fa3598d79bff2c9e\",\"name\":\"Petri Kainulainen\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/9e57425180f323fa65bc519a64c8273d3fcb7c6bd272e56b37dd15613f403659?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/9e57425180f323fa65bc519a64c8273d3fcb7c6bd272e56b37dd15613f403659?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/9e57425180f323fa65bc519a64c8273d3fcb7c6bd272e56b37dd15613f403659?s=96&d=mm&r=g\",\"caption\":\"Petri Kainulainen\"},\"description\":\"Petri is passionate about software development and continuous improvement. He is specialized in software development with the Spring Framework and is the author of Spring Data book.\",\"sameAs\":[\"http:\\\/\\\/www.petrikainulainen.net\\\/\",\"http:\\\/\\\/www.linkedin.com\\\/in\\\/petrikainulainen\",\"https:\\\/\\\/x.com\\\/https:\\\/\\\/twitter.com\\\/petrikainulaine\"],\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/author\\\/petri-kainulainen\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Spring Data Solr Tutorial: Pagination","description":"In the earlier parts of my Spring Data Solr tutorial, we have implemented a simple search function which is used to search the information of todo","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.javacodegeeks.com\/2013\/05\/spring-data-solr-tutorial-pagination.html","og_locale":"en_US","og_type":"article","og_title":"Spring Data Solr Tutorial: Pagination","og_description":"In the earlier parts of my Spring Data Solr tutorial, we have implemented a simple search function which is used to search the information of todo","og_url":"https:\/\/www.javacodegeeks.com\/2013\/05\/spring-data-solr-tutorial-pagination.html","og_site_name":"Java Code Geeks","article_publisher":"https:\/\/www.facebook.com\/javacodegeeks","article_published_time":"2013-05-31T19:00:25+00:00","article_modified_time":"2013-06-02T19:45:08+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/apache-solr-logo.jpg","type":"image\/jpeg"}],"author":"Petri Kainulainen","twitter_card":"summary_large_image","twitter_creator":"@https:\/\/twitter.com\/petrikainulaine","twitter_site":"@javacodegeeks","twitter_misc":{"Written by":"Petri Kainulainen","Est. reading time":"22 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.javacodegeeks.com\/2013\/05\/spring-data-solr-tutorial-pagination.html#article","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/2013\/05\/spring-data-solr-tutorial-pagination.html"},"author":{"name":"Petri Kainulainen","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/5af4df3fdfeb79e9fa3598d79bff2c9e"},"headline":"Spring Data Solr Tutorial: Pagination","datePublished":"2013-05-31T19:00:25+00:00","dateModified":"2013-06-02T19:45:08+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2013\/05\/spring-data-solr-tutorial-pagination.html"},"wordCount":3137,"commentCount":0,"publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2013\/05\/spring-data-solr-tutorial-pagination.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/apache-solr-logo.jpg","keywords":["Apache Solr","Spring","Spring Data"],"articleSection":["Enterprise Java"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.javacodegeeks.com\/2013\/05\/spring-data-solr-tutorial-pagination.html#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javacodegeeks.com\/2013\/05\/spring-data-solr-tutorial-pagination.html","url":"https:\/\/www.javacodegeeks.com\/2013\/05\/spring-data-solr-tutorial-pagination.html","name":"Spring Data Solr Tutorial: Pagination","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2013\/05\/spring-data-solr-tutorial-pagination.html#primaryimage"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2013\/05\/spring-data-solr-tutorial-pagination.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/apache-solr-logo.jpg","datePublished":"2013-05-31T19:00:25+00:00","dateModified":"2013-06-02T19:45:08+00:00","description":"In the earlier parts of my Spring Data Solr tutorial, we have implemented a simple search function which is used to search the information of todo","breadcrumb":{"@id":"https:\/\/www.javacodegeeks.com\/2013\/05\/spring-data-solr-tutorial-pagination.html#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.javacodegeeks.com\/2013\/05\/spring-data-solr-tutorial-pagination.html"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/2013\/05\/spring-data-solr-tutorial-pagination.html#primaryimage","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/apache-solr-logo.jpg","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/apache-solr-logo.jpg","width":150,"height":150},{"@type":"BreadcrumbList","@id":"https:\/\/www.javacodegeeks.com\/2013\/05\/spring-data-solr-tutorial-pagination.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.javacodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"Java","item":"https:\/\/www.javacodegeeks.com\/category\/java"},{"@type":"ListItem","position":3,"name":"Enterprise Java","item":"https:\/\/www.javacodegeeks.com\/category\/java\/enterprise-java"},{"@type":"ListItem","position":4,"name":"Spring Data Solr Tutorial: Pagination"}]},{"@type":"WebSite","@id":"https:\/\/www.javacodegeeks.com\/#website","url":"https:\/\/www.javacodegeeks.com\/","name":"Java Code Geeks","description":"Java Developers Resource Center","publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"alternateName":"JCG","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.javacodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.javacodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.javacodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/javacodegeeks","https:\/\/x.com\/javacodegeeks"]},{"@type":"Person","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/5af4df3fdfeb79e9fa3598d79bff2c9e","name":"Petri Kainulainen","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/9e57425180f323fa65bc519a64c8273d3fcb7c6bd272e56b37dd15613f403659?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/9e57425180f323fa65bc519a64c8273d3fcb7c6bd272e56b37dd15613f403659?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/9e57425180f323fa65bc519a64c8273d3fcb7c6bd272e56b37dd15613f403659?s=96&d=mm&r=g","caption":"Petri Kainulainen"},"description":"Petri is passionate about software development and continuous improvement. He is specialized in software development with the Spring Framework and is the author of Spring Data book.","sameAs":["http:\/\/www.petrikainulainen.net\/","http:\/\/www.linkedin.com\/in\/petrikainulainen","https:\/\/x.com\/https:\/\/twitter.com\/petrikainulaine"],"url":"https:\/\/www.javacodegeeks.com\/author\/petri-kainulainen"}]}},"_links":{"self":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/13342","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/users\/429"}],"replies":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/comments?post=13342"}],"version-history":[{"count":0,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/13342\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media\/80"}],"wp:attachment":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media?parent=13342"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/categories?post=13342"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/tags?post=13342"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}