Spring Data Solr教程:分页

在我的Spring Data Solr教程的较早部分中,我们实现了一个简单的搜索功能,该功能用于搜索待办事项的信息。 我们搜索功能的当前实现将所有搜索结果显示在一个页面中。 对于大多数现实生活中的应用程序而言,这不是可行的解决方案,因为搜索结果的数量可能太大,以致搜索功能不再可用。

这篇博客文章描述了如何使用Spring Data Solr对查询结果或搜索功能进行分页,从而为我们提供了解决该问题的方法。

这篇博客文章分为五个部分:

  • 第一部分描述了如何手动请求正确的页面,并讨论了查询方法的不同返回类型。
  • 第二部分描述了如何通过向存储库中添加自定义方法来获取搜索结果计数。
  • 第三部分介绍了如何对查询方法的搜索结果进行分页。
  • 第四部分教我们如何对动态查询的搜索结果进行分页。
  • 第五部分也是最后一部分描述了如何配置和使用一种称为Web分页的技术。

注意 :这些博客文章提供了其他信息,可帮助我们理解此博客文章中描述的概念:

  • 使用Maven运行Solr
  • Spring Data Solr教程:Solr简介
  • Spring Data Solr教程:配置
  • Spring Data Solr教程CRUD(几乎)
  • Spring Data Solr教程:将自定义方法添加到单个存储库
  • Spring Data Solr教程:动态查询
  • Spring Data Solr教程:排序

让我们开始吧。

理论纪要

在开始对示例应用程序进行修改之前,我们将简要介绍分页背后的理论。 本节分为两个小节,如下所述:

  • 第一部分描述了如何指定查询的分页选项。
  • 第二部分描述查询方法的不同返回类型。

让我们继续。

指定想要的页面

使用的分页选项是通过使用实现Pageable接口的PageRequest类指定的。

以下是典型的分页要求:

  • 获取属于单个页面的查询结果。
  • 使用单个字段的值对查询结果进行排序时,获取属于单个页面的查询结果。
  • 使用多个字段的值对查询结果进行排序并且不同字段的排序顺序相同时,获取属于单个页面的查询结果。
  • 使用多个字段的值对查询结果进行排序并且不同字段的排序顺序不同时,获取属于单个页面的查询结果。

让我们找出如何创建满足给定要求的PageRequest对象。

首先,我们必须创建一个PageRequest对象,该对象指定我们要获取属于单个页面的查询结果。 我们可以使用以下代码创建PageRequest对象:

//Get the query results belonging to the first page when page size is 10.
new PageRequest(0, 10)

其次,我们必须创建一个PageRequest对象,该对象指定当使用单个字段的值对查询结果进行排序时,我们希望获得属于单个页面的结果。 我们可以使用以下代码创建PageRequest对象:

/Gets the query results belonging to the first page when page size is 10.
//Query results are sorted in descending order by using id field.
new PageRequest(0, 10 Sort.Direction.DESC, "id")

第三,我们必须创建一个PageRequest对象,该对象指定当使用多个字段对查询结果进行排序并且不同字段的排序顺序相同时,我们希望获取属于单个页面的结果。 我们可以使用以下代码创建PageRequest对象:

//Gets the query results belonging to the first page when page size is 10.
//Query results are sorted in descending order by using id and description fields.
new PageRequest(0, 10 Sort.Direction.DESC, "id", "description")

第四,我们必须创建一个PageRequest对象,该对象指定当使用多个字段对查询结果进行排序并且不同字段的排序顺序不同时,要获取属于单个页面的查询结果。 我们可以使用以下代码创建该对象:

//Gets the query results belonging to the first page when page size is 10.
//Query results are sorted in descending order order by using the description field
//and in ascending order by using the id field.
Sort sort = new Sort(Sort.Direction.DESC, "description").and(new Sort(Sort.Direction.ASC, "id"))
new PageRequest(0, 10, sort);

现在我们知道如何创建新的PageRequest对象。 让我们继续讨论查询方法的不同返回类型。

确定查询方法的返回类型

当查询方法使用分页时,它可以具有两种返回类型。 这些返回类型将在下面进行描述(我们将假定模型类的名称为TodoDocument ):

  • 当我们对分页元数据感兴趣时,查询方法的返回类型必须为Page <TodoDocument> (获取有关Page接口的更多信息,该接口声明用于获取分页元数据的方法)。
  • 当我们对分页元数据不感兴趣时​​,查询方法的返回类型应为List <TodoDocument>

获取搜索结果计数

在开始对查询的搜索结果进行分页之前,我们必须实现一个函数,该函数用于获取与给定搜索条件匹配的待办事项条目数。 此数字是必需的,以便我们可以在前端实现分页逻辑。

我们可以按照以下步骤实现此功能:

  1. 将自定义方法添加到我们的存储库。 此方法用于返回搜索结果计数。
  2. 使用我们的自定义存储库方法创建一个新的服务方法。

在以下小节中将更详细地描述这些步骤。

向我们的存储库添加自定义方法

目前,如果不向存储库中添加自定义方法,就无法创建计数查询。 我们可以按照以下步骤进行操作:

  1. 创建一个定制的存储库界面。
  2. 实现定制存储库接口。
  3. 修改实际的存储库界面。

让我们继续前进,找出实现方法。

创建自定义存储库界面

我们可以按照以下步骤创建自定义存储库接口:

  1. 创建一个名为CustomTodoDocumentRepository的接口。
  2. count()方法添加到创建的接口。 该方法将使用的搜索词作为方法参数。

CustomTodoDocumentRepository接口的源代码如下所示:

public interface CustomTodoDocumentRepository {public long count(String searchTerm);//Other methods are omitted
}

实施自定义存储库界面

我们可以按照以下步骤实现自定义存储库接口:

  1. 创建一个名为TodoDocumentRepositoryImpl的类,并实现CustomTodoDocumentRepository接口。
  2. @Repository批注对类进行批注。
  3. SolrTemplate字段添加到类中,并使用@Resource注释对字段进行注释。
  4. 实现count()方法。

让我们仔细看一下count()方法的实现。 我们可以通过执行以下步骤来实现此方法:

  1. 获取给定搜索词的单词。
  2. 通过调用私有的constructSearchConditions()方法来构造使用的搜索条件,并将搜索词的单词作为方法参数传递。
  3. 通过创建新的SimpleQuery对象来创建执行的查询,并将创建的Criteria对象作为构造函数参数传递。
  4. 通过调用SolrTemplate类的count()方法获取搜索结果计数,并将创建的SimpleQuery对象作为方法参数传递。
  5. 返回搜索结果计数。

TodoDocumentRepositoryImpl类的源代码如下所示:

import org.springframework.data.solr.core.SolrTemplate;
import org.springframework.data.solr.core.query.Criteria;
import org.springframework.data.solr.core.query.SimpleQuery;
import org.springframework.stereotype.Repository;import javax.annotation.Resource;@Repository
public class TodoDocumentRepositoryImpl implements CustomTodoDocumentRepository {@Resourceprivate SolrTemplate solrTemplate;@Overridepublic long count(String searchTerm) {String[] words = searchTerm.split(" ");Criteria conditions = createSearchConditions(words);SimpleQuery countQuery = new SimpleQuery(conditions);return solrTemplate.count(countQuery);}private Criteria createSearchConditions(String[] words) {Criteria conditions = null;for (String word: words) {if (conditions == null) {conditions = new Criteria("title").contains(word).or(new Criteria("description").contains(word));}else {conditions = conditions.or(new Criteria("title").contains(word)).or(new Criteria("description").contains(word));}}return conditions;}//Other methods are omitted.
}

修改实际存储库界面

通过扩展CustomTodoRepositoryInterface,我们可以使自定义count()方法对我们的存储库用户可见。 TodoDocumentRepository的源代码如下所示:

public interface TodoDocumentRepository extends CustomTodoRepository, SolrCrudRepository<TodoDocument, String> {//Repository methods are omitted.
}

使用自定义存储库方法

我们可以按照以下步骤使用创建的存储库方法:

  1. 修改TodoIndexService接口。
  2. 实现修改后的接口。

下面将更详细地描述这些步骤。

注意 :我们还必须进行其他更改,但是由于它们与Spring Data Solr不相关,因此在此不再赘述。

修改服务接口

我们必须通过向其添加一个新的countSearchResults()方法来修改TodoIndexService接口。 此方法将使用的搜索词作为方法参数,并返回搜索结果计数。 TodoIndexService接口的源代码如下所示:

public interface TodoIndexService {public long countSearchResults(String searchTerm);//Other methods are omitted.
}

实施修改后的接口

通过执行以下步骤,我们可以实现countSearchResults()方法:

  1. countSearchResults()方法添加到RepositoryTodoIndexService类。
  2. 通过调用自定义存储库方法获取搜索结果计数,然后返回搜索结果计数。

RepositoryTodoIndexService类的相关部分如下所示:

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;@Service
public class RepositoryTodoIndexService implements TodoIndexService {@Resourceprivate TodoDocumentRepository repository;@Overridepublic long countSearchResults(String searchTerm) {return repository.count(searchTerm);}//Other methods are omitted.
}

分页查询方法的查询结果

使用查询方法创建查询时,可以按照以下步骤对查询结果进行分页:

  1. 将新的Pageable参数添加到查询方法。 此参数指定获取的页面的详细信息。
  2. 通过将新的Pageable参数添加到TodoIndexService接口的search()方法来修改服务层。

让我们开始吧。

修改存储库界面

我们可以通过向查询方法添加Pageable参数来向我们的存储库添加分页支持,该方法用于构建执行的查询。 让我们看一下查询方法的声明。

从方法名称查询生成

通过使用从方法名策略生成查询来创建执行的查询时,我们必须向TodoDocumentRepository接口的findByTitleContainsOrDescriptionContains()方法添加Pageable参数。 我们的存储库界面的这些源代码如下所示:

import org.springframework.data.domain.Pageable;
import org.springframework.data.solr.repository.SolrCrudRepository;import java.util.List;public interface TodoDocumentRepository extends CustomTodoDocumentRepository, SolrCrudRepository<TodoDocument, String> {public List<TodoDocument> findByTitleContainsOrDescriptionContains(String title, String description, Pageable page);
}

命名查询

使用命名查询时,我们必须在TodoDocumentRepository接口的findByNamedQuery()方法中添加Pageable参数。 TodoDocumentRepository接口的源代码如下所示:

import org.springframework.data.domain.Pageable;
import org.springframework.data.solr.repository.Query;
import org.springframework.data.solr.repository.SolrCrudRepository;import java.util.List;public interface TodoDocumentRepository extends CustomTodoDocumentRepository, SolrCrudRepository<TodoDocument, String> {@Query(name = "TodoDocument.findByNamedQuery")public List<TodoDocument> findByNamedQuery(String searchTerm, Pageable page);
}

@Query注释

使用@Query批注创建执行的查询时,我们必须在TodoDocumentRepository接口的findByQueryAnnotation()方法中添加Pageable参数。 我们的存储库界面的源代码如下所示:

import org.springframework.data.domain.Pageable;
import org.springframework.data.solr.repository.Query;
import org.springframework.data.solr.repository.SolrCrudRepository;import java.util.List;public interface TodoDocumentRepository extends CustomTodoDocumentRepository, SolrCrudRepository<TodoDocument, String> {@Query("title:*?0* OR description:*?0*")public List<TodoDocument> findByQueryAnnotation(String searchTerm, Pageable page);
}

修改服务层

我们必须对示例应用程序的服务层进行以下修改:

  1. 将一个Pageable参数添加到TodoIndexService接口的search()方法。
  2. 实现新的search()方法。

注意 :我们还必须进行其他更改,但是由于它们与Spring Data Solr不相关,因此在此不再赘述。

TodoIndexService接口的源代码如下所示:

import org.springframework.data.domain.Pageable;
import java.util.List;public interface TodoIndexService {public List<TodoDocument> search(String searchTerm, Pageable page);//Other methods are omitted.
}

我们可以通过对RepositoryIndexService类的search()方法进行以下更改来使用修改后的查询方法:

  1. 通过调用存储库的查询方法来获取分页查询结果,并将使用的搜索词和Pageable对象作为方法参数传递。
  2. 返回查询结果。

让我们来看一下search()方法的不同实现。

从方法名称查询生成

通过使用从方法名策略生成查询来构建查询时,可以使用TodoDocumentRepository接口的findByTitleContainsOrDescriptionContains()方法获取属于特定页面的查询结果。

RepositoryTodoIndexService类的相关部分如下所示:

import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;@Service
public class RepositoryTodoIndexService implements TodoIndexService {@Resourceprivate TodoDocumentRepository repository;@Overridepublic List<TodoDocument> search(String searchTerm, Pageable page) {return repository.findByTitleContainsOrDescriptionContains(searchTerm, searchTerm, page);}//Other methods are omitted
}

命名查询

当我们使用命名查询来构建执行的查询时,可以使用TodoDocumentRepository接口的findByNamedQuery()方法获取属于特定页面的搜索结果。

RepositoryTodoIndexService类的相关部分如下所示:

import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;@Service
public class RepositoryTodoIndexService implements TodoIndexService {@Resourceprivate TodoDocumentRepository repository;@Overridepublic List<TodoDocument> search(String searchTerm, Pageable page) {return repository.findByNamedQuery(searchTerm, page);}//Other methods are omitted
}

@Query注释

使用@Query批注构建查询时,可以通过调用TodoDocumentRepository接口的findByQueryAnnotation()方法来获取属于特定页面的搜索结果。

RepositoryTodoIndexService类的源代码如下所示:

import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;@Service
public class RepositoryTodoIndexService implements TodoIndexService {@Resourceprivate TodoDocumentRepository repository;@Overridepublic List<TodoDocument> search(String searchTerm, Pageable page) {return repository.findByQueryAnnotation(searchTerm, page);}//Other methods are omitted
}

分页动态查询的查询结果

我们可以按照以下步骤对动态查询的查询结果进行分页:

  1. 将Pageable参数添加到我们的自定义存储库的search()方法中。
  2. 通过将Pageable参数添加到TodoIndexService接口的search()方法来修改服务层。

在以下小节中将更详细地描述这些步骤。

更改自定义存储库

我们必须向我们的自定义存储库添加分页支持。 我们可以按照以下步骤进行操作:

  1. 通过将Pageable参数添加到其search()方法来修改自定义存储库接口。
  2. 通过向其添加分页支持来更改search()方法的实现。

让我们继续前进,找出实现方法。

更改自定义存储库界面

我们必须在CustomTodoDocumentRepository接口中声明的search()方法中添加Pageable参数。 我们的自定义存储库界面的源代码如下所示:

import org.springframework.data.domain.Pageable;import java.util.List;public interface CustomTodoDocumentRepository {public List<TodoDocument> search(String searchTerm, Pageable page);//Other methods are omitted.
}

实施自定义存储库方法

我们的下一步是向search()方法的实现中添加分页支持。 通过执行以下步骤,我们可以实现TodoDocumentRepositoryImpl类的search()方法:

  1. 获取搜索词的单词。
  2. 通过调用私有createSearchConditions()方法并将搜索词的单词作为方法参数来构造使用的搜索条件。
  3. 通过创建新的SimpleQuery对象来创建执行的查询,并将创建的Criteria对象作为构造函数参数传递。
  4. 通过调用SimpleQuery类的setPageRequest()方法来设置查询的分页选项。 将Pageable对象作为方法参数传递。
  5. 通过调用SolrTemplate类的queryForPage()方法获取搜索结果。 将创建的查询和期望的返回对象的类型作为方法参数传递。
  6. 通过调用Page接口的getContent()方法来返回搜索结果。

TodoDocumentRepositoryImpl类的源代码如下所示:

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.solr.core.SolrTemplate;
import org.springframework.data.solr.core.query.Criteria;
import org.springframework.data.solr.core.query.SimpleQuery;
import org.springframework.stereotype.Repository;import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;@Repository
public class TodoDocumentRepositoryImpl implements CustomTodoDocumentRepository {@Resourceprivate SolrTemplate solrTemplate;@Overridepublic List<TodoDocument> search(String searchTerm, Pageable page) {String[] words = searchTerm.split(" ");Criteria conditions = createSearchConditions(words);SimpleQuery search = new SimpleQuery(conditions);search.setPageRequest(page);Page results = solrTemplate.queryForPage(search, TodoDocument.class);return results.getContent();}private Criteria createSearchConditions(String[] words) {Criteria conditions = null;for (String word: words) {if (conditions == null) {conditions = new Criteria("title").contains(word).or(new Criteria("description").contains(word));}else {conditions = conditions.or(new Criteria("title").contains(word)).or(new Criteria("description").contains(word));}}return conditions;}//Other methods are omitted.
}

使用自定义存储库

在使用修改后的存储库方法之前,我们必须对示例应用程序的服务层进行以下更改:

  1. 将一个Pageable参数添加到TodoIndexService接口的search()方法。
  2. 实现search()方法。

下面将更详细地描述这些步骤。

注意 :我们还必须进行其他更改,但是由于它们与Spring Data Solr不相关,因此在此不再赘述。

修改服务接口

我们必须向TodoIndexService接口的search()方法添加Pageable参数。 TodoIndexService的源代码如下所示:

import org.springframework.data.domain.Pageable;
import java.util.List;public interface TodoIndexService {public List<TodoDocument> search(String searchTerm, Pageable page);//Other methods are omitted.
}

实施服务接口

当使用Spring Data Solr的标准API进行构建时,我们可以通过调用自定义存储库的search()方法并将用户搜索词和Pageable对象作为方法参数来获取查询结果。

RepositoryTodoIndexService类的源代码如下所示:

import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;@Service
public class RepositoryTodoIndexService implements TodoIndexService {@Resourceprivate TodoDocumentRepository repository;@Overridepublic List<TodoDocument> search(String searchTerm, Pageable page) {return repository.search(searchTerm, page);}//Other methods are omitted.
}

使用网页分页

一个问题仍然没有答案。 问题是:

在何处指定用于对查询的查询结果进行分页的分页选项?

我们将使用称为Web pagination的技术来创建查询的分页选项。 此技术基于称为PageableArgumentResolver的自定义参数解析器类。 此类解析来自HTTP请求的分页信息,并使向控件方法添加Pageable方法参数成为可能。

本节描述了如何在示例应用程序中配置和使用此技术。 它分为三个小节:

  • 第一部分描述了如何配置PageableArgumentResolver类。
  • 第二小节介绍了如何使用它。
  • 最后一个小节讨论了Web分页的利弊。

让我们找出如何在示例应用程序中使用此技术。

组态

本小节描述了如何配置PageableArgumentResolver类,该类将用于从HTTP请求中提取分页选项。 让我们找出如何通过使用Java配置和XML配置来做到这一点。

Java配置

我们可以通过对ExampleApplicationContext类进行以下更改来添加自定义参数自变量解析器:

  1. 重写WebMvcConfigurerAdapter类的addArgumentResolvers()方法。
  2. 通过创建新的PageableArgumentResolver对象并将创建的对象添加到作为方法参数给出的参数解析器列表中,实现addArgumentResolvers()方法。

ExampleApplicationContext类的相关部分如下所示:

import org.springframework.data.web.PageableArgumentResolver;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.mvc.method.annotation.ServletWebArgumentResolverAdapter;import java.util.List;//Annotations are omitted.
public class ExampleApplicationContext extends WebMvcConfigurerAdapter {@Overridepublic void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {PageableArgumentResolver pageableArgumentResolver = new PageableArgumentResolver();argumentResolvers.add(new ServletWebArgumentResolverAdapter(pageableArgumentResolver));}//Other methods are omitted.
}

XML配置

我们可以通过对exampleApplicationContext.xml文件进行以下更改来配置自定义参数解析程序:

  1. 使用mvc命名空间的arguments-resolvers元素配置自定义参数解析器。
  2. arguments-resolvers元素内配置PageableArgumentResolver bean。

exampleApplicationContext.xml文件的相关部分如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:mvc="http://www.springframework.org/schema/mvc"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd"><mvc:annotation-driven><mvc:argument-resolvers><bean id="pageagleArgumentResolver" class="org.springframework.data.web.PageableArgumentResolver"/></mvc:argument-resolvers></mvc:annotation-driven><!-- Configuration is omitted. -->
</beans>

用法

使用前面介绍的方法之一配置PageableArgumentResolver类后,可以将Pageable方法参数添加到控制器方法中。 TodoController类的search()方法就是一个很好的例子。 其源代码的相关部分如下所示:

import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;import javax.annotation.Resource;
import java.util.List;@Controller
public class TodoController {//Fields are omitted.@RequestMapping(value = "/api/todo/search/{searchTerm}", method = RequestMethod.GET)@ResponseBodypublic List<TodoDTO> search(@PathVariable("searchTerm") String searchTerm, Pageable page) {//Implementation is omitted.}//Other methods are omitted.
}

但是,将Pageable参数添加到controller方法还不够。 我们仍然必须将分页选项添加到HTTP请求。 这是通过在请求中添加特殊的请求参数来完成的。 这些请求参数描述如下:

  • page.page request参数指定所请求的页面。
  • page.size请求参数指定页面大小。
  • page.sort请求参数指定用于对查询结果进行排序的属性。
  • page.sort.dir请求参数指定排序顺序。

让我们花点时间思考一下Web分页的利弊。

利弊

在决定在我们的应用程序中使用它之前,我们应该意识到Web分页的优缺点。 让我们找出它们是什么。

优点

使用网页分页有一个主要好处:

将分页选项从Web层转移到存储库层是一件容易的事。 我们要做的就是配置自定义参数解析器,将Pageable参数添加到控制器方法,并使用特定的请求参数发送分页选项。 这比处理代码中的分页选项和手动创建PageRequest对象要简单得多。

缺点

下面介绍了使用Web分页的缺点:

  • Web分页在Web层和Spring Data之间创建依赖关系。 这意味着存储库层的实现细节会泄漏到应用程序的上层。 尽管纯粹主义者可能会声称这是一个巨大的错误,但我不同意他们的观点。 我认为抽象应该使我们的生活更轻松,而不是更艰难。 我们还必须记住, 泄漏抽象定律规定,所有非平凡抽象在某种程度上都是泄漏的。
  • Web分页的一个真正的缺点是,只有在使用单个字段对搜索结果进行排序的情况下,我们才能使用它。 尽管对于大多数用例来说这是完全可以的,但在某些情况下这会成为问题。 如果发生这种情况,我们必须手动处理分页选项。

摘要

现在,我们已将分页搜索结果添加到示例应用程序中。 本教程教会了我们以下内容:

  • 我们学习了创建新的PageRequest对象。
  • 我们了解到可以从两个不同的选项中选择查询方法的返回类型。
  • 我们学习了对查询方法和动态查询的查询结果进行分页。
  • 我们知道如何使用网页分页,并且知道它的优缺点。

我的Spring Data Solr教程的下一部分描述了如何向所有Spring Data Solr存储库添加自定义方法。

PS此博客文章的示例应用程序可在Github上获得( 查询方法和动态查询 )。

参考: Spring Data Solr教程: Petri Kainulainen博客上我们JCG合作伙伴 Petri Kainulainen的分页 。

翻译自: https://www.javacodegeeks.com/2013/05/spring-data-solr-tutorial-pagination.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/368307.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

消息队列01

公司项目里面用到了这个rabbitmq&#xff0c;自己以前不熟悉&#xff0c;看了代码里面的应用&#xff0c;自己也准备试着搭建下。 可以参照其他博主的这篇优秀博文&#xff1a; https://www.cnblogs.com/chengpeng15/p/5814197.html 一 前期需要了解的概念 1.什么是异步&#x…

java instanceof翻译_Java 中的instanceof简单讲解

Java 中的instanceof 运算符是用来在运行时指出对象是否是特定类的一个实例。instanceof通过返回一个布尔值来指出&#xff0c;这个对象是否是这个特定类或者是它的子类的一个实例。用法&#xff1a;result object instanceof class参数&#xff1a;Result&#xff1a;布尔类型…

Spring4有条件

Spring 4引入了一个称为Conditional的新功能&#xff0c;该功能针对于生成bean的Spring组件&#xff0c;并注视这些bean的生成&#xff0c;实质上&#xff0c;它提供了一种条件生成bean的方法。 考虑一个简单的例子&#xff1a; 我有一个名为“ CustomerService”的服务&…

inline「一」:从 image 底部白边初识 line-height

本文首发于个人博客 http://www.lijundong.com/image-and-line-height/ 今天在做一个静态页面时&#xff0c;图片底部出现一条 3px 高度的白边&#xff0c;既不是 margin 也不是 padding&#xff0c;找了好久没能解决&#xff0c;后来才发现与 line-height 相关&#xff0c;问…

(转) STM32--ADC

原标题&#xff1a;STM32之ADC步骤小技巧&#xff08;英文&#xff09; 看到标题&#xff0c;别吓到哈、并不是要用英文写、至于原因是什么、请往下看&#xff1a; 言归正传&#xff1a;STM32的ADC模块的特色 1、1MHz转换速率、12位转换结果&#xff08;12位、记住这个12位哈、…

java resultset 映射到实例_[Java]ResultSet的用法与实例

JDBC API 2.0/3.0中ResultSet记录集的简便实用的新特性1 新定义了若干个常数这些常数用于指定ResultSet 的类型游标移动的方向等性质&#xff0c;如下所示&#xff1a;public static final int FETCH_FORWARD; 该常数的作用是指定处理记录集中行的顺序&#xff0c;是由前到后即…

嗨,那里有回调!

因为是我的书包&#xff0c;所以我喜欢JavaScript 。 实际上&#xff0c;我已经开始喜欢JavaScritp的面向异步回调的编程风格 。 因此&#xff0c;当我发现自己处于非JavaScript环境中时&#xff08;例如Java&#xff09; &#xff0c;我往往会错过使用回调的机会。 好消息是…

python2.x 文件读写

打开文件 f open(filename,type) # filename 是文件所在路径# type 为文件打开的方式&#xff0c;也是字符串 读取单行 oneLineStr f.readline() 读取所有&#xff0c;一行一行读取 allInLines f.readlines() 读取所有&#xff0c;返回一个字符串 all f.read() 去除字符串开…

synchronized 修饰在 static方法和非static方法的区别

Java中synchronized用在静态方法和非静态方法上面的区别 在Java中&#xff0c;synchronized是用来表示同步的&#xff0c;我们可以synchronized来修饰一个方法。也可以synchronized来修饰方法里面的一个语句块。那么&#xff0c;在static方法和非static方法前面加synchronized到…

Flexible 弹性盒子模型之CSS justify-content 属性

实例 在弹性盒对象的 <div> 元素中的各项周围留有空白&#xff1a; div{display: flex;justify-content: space-around;} 复制 效果预览 浏览器支持 表格中的数字表示支持该属性的第一个浏览器的版本号。 紧跟在 -webkit-, -ms- 或 -moz- 后的数字为支持该前缀属性的第一…

java标识符可以$开头吗_JAVA标识符

JAVA标识符JAVA标识符简介Java语言中&#xff0c;对于变量&#xff0c;常量&#xff0c;函数&#xff0c;语句块也有名字&#xff0c;我们统统称之为Java标识符。也就是程序员在定义java程序时&#xff0c;自定义的一些名字&#xff0c;例如helloworld 程序里关键字class后跟的…

GC内存可视化器教程–第一部分

正如您从以前的文章中可能已经读到的那样&#xff0c;要获得的Java程序员的一项关键技能就是理解和评估JVM的运行状况的能力&#xff0c;例如Java堆内存占用量以及垃圾回收过程。 为了实现上述目标&#xff0c;所有JVM供应商&#xff08;Oracle&#xff0c;IBM等&#xff09;都…

设置表格边框颜色

1、源码如下&#xff1a; <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html><head><title>设置表格边框颜色</title><meta http-equiv"keywords" content"keyword1,keyword2,keyword3"…

图片热点

图片热点&#xff1a; 规划出图片上的一个区域&#xff0c;可以做出超链接&#xff0c;直接点击图片区域就可以完成跳转的效果 网页划区&#xff1a; 在一个网页里&#xff0c;规划出一个区域用来展示另一个网页的内容。 网页的拼接&#xff1a; 在一个网络页面内&#xff0c;规…

java se程序设计_JavaSE--Java 的基本程序设计结构

Java 对大小写敏感Java 中定义类名的规则很宽松。名字必须以字母开头&#xff0c;后面可以跟字母和数字的任意组合。长度基本上没有限制。但是不能使用 Java 保留字作为类名。标准的命名规范为&#xff1a;类名是以大写字母开头的名词。如果名字由多个单词组成&#xff0c;每个…

Python开发【第十九篇】:Python操作MySQL

本篇对于Python操作MySQL主要使用两种方式&#xff1a; 原生模块 pymsqlORM框架 SQLAchemypymsql pymsql是Python中操作MySQL的模块&#xff0c;其使用方法和MySQLdb几乎相同。 下载安装 1pip3 install pymysql使用操作 1、执行SQL 123456789101112131415161718192021222324252…

Javaone 2013评论

tl; dr我今年再次参加了Javaone。 好玩。 星期日 会议于周日开幕&#xff0c;进行了用户组会议和主要主题演讲。 实际上&#xff0c;由于我正在运行有关Java SE 7和8中新功能的Java大学培训课程&#xff0c;所以我实际上无法参加这些课程。该课程涵盖了Java 7的项目硬币&#…

20180705 考试记录

T1 货物运输弱化版 题解&#xff1a; 倒着跑最短路就行没仔细看题凉凉 code: #include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #define F(i,a,b) for(register int i(a);i<(b);i) using namespace std;int rd() {int x…

mysql集群跨地域同步部署_跨地域冗余 - 跨数据中心部署方案 - 《TiDB v2.1 用户文档》 - 书栈网 · BookStack...

跨数据中心部署方案作为 NewSQL 数据库&#xff0c;TiDB 兼顾了传统关系型数据库的优秀特性以及 NoSQL 数据库可扩展性&#xff0c;以及跨数据中心(下文简称“中心”)场景下的高可用。本文档旨在介绍跨数据中心部署的不同解决方案。三中心部署方案TiDB, TiKV, PD 分别分布在 3 …

Flexible 弹性盒子模型之CSS align-items 属性

实例 居中对齐弹性盒的各项 <div> 元素&#xff1a; div{display: flex;align-items:center;} 复制 效果预览 浏览器支持 表格中的数字表示支持该属性的第一个浏览器的版本号。 紧跟在 -webkit-, -ms- 或 -moz- 后的数字为支持该前缀属性的第一个版本。 属性 align-i…