Spring Data Commons 的 Pageable 接口提供了一种标准化的方法来获取分页结果。它允许在不考虑底层存储机制的情况下请求具有指定页大小和页码的数据。Page 接口是对 Pageable 结果的封装,它提供了总元素数、总页数以及当前页码等元数据信息。

通过使用这些接口,开发人员可以轻松地在应用程序中实现分页,而无需关心底层存储细节。这简化了分页操作,提高了代码可读性和可维护性。

Spring Data Extensions

  • Querydsl 支持,允许通过流畅的 API 构建类型安全 SQL 查询。

  • Web 支持,包括以下功能:

  • 使用域类转换器在控制器方法签名中直接使用域类型。

  • 解析 Pageable 和 Sort 实例,并允许自定义默认配置。

  • 创建 JSON 页面的表示形式,以呈现 Spring Data 页面的内容。

  • 超媒体支持,允许将链接添加到页面的表示形式中,以便轻松浏览。

  • Spring Data Jackson 模块,用于绑定和反绑定 Spring Data 类型的 JSON 表示形式。

  • Web 数据绑定支持,允许使用 JSONPath 或 XPath 表达式将传入请求有效负载绑定到 Spring MVC 处理程序方法参数。

  • Querydsl Web 支持,允许从请求查询字符串中包含的属性派生查询。

  • 存储库填充器,用于使用 JSON 或 XML 数据填充存储库。

本节记录了一组 Spring Data 扩展,它能够在各种上下文中使用 Spring Data。当前,大部分集成都针对 Spring MVC。

This section documents a set of Spring Data extensions that enable Spring Data usage in a variety of contexts. Currently, most of the integration is targeted towards Spring MVC.

Querydsl Extension

Querydsl 是一个框架,通过其流畅 API 启用静态类型 SQL 式查询的构建。

Querydsl is a framework that enables the construction of statically typed SQL-like queries through its fluent API.

多个 Spring Data 模块都通过“QuerydslPredicateExecutor”提供与 Querydsl 的集成,如下面的示例所示:

Several Spring Data modules offer integration with Querydsl through QuerydslPredicateExecutor, as the following example shows:

QuerydslPredicateExecutor interface
public interface QuerydslPredicateExecutor<T> {

  Optional<T> findById(Predicate predicate);  1

  Iterable<T> findAll(Predicate predicate);   2

  long count(Predicate predicate);            3

  boolean exists(Predicate predicate);        4

  // … more functionality omitted.
}
1 Finds and returns a single entity matching the Predicate.
2 Finds and returns all entities matching the Predicate.
3 Returns the number of entities matching the Predicate.
4 Returns whether an entity that matches the Predicate exists.

如以下示例所示,要使用 Querydsl 支持,请在你的存储库接口上扩展“QuerydslPredicateExecutor”:

To use the Querydsl support, extend QuerydslPredicateExecutor on your repository interface, as the following example shows:

Querydsl integration on repositories
interface UserRepository extends CrudRepository<User, Long>, QuerydslPredicateExecutor<User> {
}

上述示例允许你使用 Querydsl “Predicate”实例编写类型安全查询,如下例所示:

The preceding example lets you write type-safe queries by using Querydsl Predicate instances, as the following example shows:

Predicate predicate = user.firstname.equalsIgnoreCase("dave")
	.and(user.lastname.startsWithIgnoreCase("mathews"));

userRepository.findAll(predicate);

Web support

支持存储库编程模型的 Spring Data 模块随各种 Web 支持一起提供。Web 相关组件需要 Spring MVC JAR 在类路径上。其中一些甚至提供与 Spring HATEOAS 的集成。通常,通过在 JavaConfig 配置类中使用 @EnableSpringDataWebSupport 注释启用集成支持,如以下示例所示:

Spring Data modules that support the repository programming model ship with a variety of web support. The web related components require Spring MVC JARs to be on the classpath. Some of them even provide integration with Spring HATEOAS. In general, the integration support is enabled by using the @EnableSpringDataWebSupport annotation in your JavaConfig configuration class, as the following example shows:

Enabling Spring Data web support
  • Java

  • XML

@Configuration
@EnableWebMvc
@EnableSpringDataWebSupport
class WebConfiguration {}
<bean class="org.springframework.data.web.config.SpringDataWebConfiguration" />

<!-- If you use Spring HATEOAS, register this one *instead* of the former -->
<bean class="org.springframework.data.web.config.HateoasAwareSpringDataWebConfiguration" />

@EnableSpringDataWebSupport”注释会注册一些组件。我们将在本节后面讨论这些组件。它还检测类路径上的 Spring HATEOAS,以及为其注册集成组件(如果存在)。

The @EnableSpringDataWebSupport annotation registers a few components. We discuss those later in this section. It also detects Spring HATEOAS on the classpath and registers integration components (if present) for it as well.

Basic Web Support

Enabling Spring Data web support in XML

previous section 中显示的配置注册了一些基本组件:

Enabling Spring Data web support in XML

The configuration shown in the previous section registers a few basic components:

  • A Using the DomainClassConverter Class to let Spring MVC resolve instances of repository-managed domain classes from request parameters or path variables.

  • HandlerMethodArgumentResolver implementations to let Spring MVC resolve Pageable and Sort instances from request parameters.

  • Jackson Modules to de-/serialize types like Point and Distance, or store specific ones, depending on the Spring Data Module used.

Using the DomainClassConverter Class

DomainClassConverter”类允许你在 Spring MVC 控制器方法签名中直接使用域类型,这样你就不必通过存储库手动查找实例,如下例所示:

The DomainClassConverter class lets you use domain types in your Spring MVC controller method signatures directly so that you need not manually lookup the instances through the repository, as the following example shows:

A Spring MVC controller using domain types in method signatures
@Controller
@RequestMapping("/users")
class UserController {

  @RequestMapping("/{id}")
  String showUserForm(@PathVariable("id") User user, Model model) {

    model.addAttribute("user", user);
    return "userForm";
  }
}

此方法直接接收“用户”实例,无需进一步查找。可以通过让 Spring MVC 将路径变量转换为域类别的“id”类型,然后最终通过调用域类型注册的存储库实例的“findById(…)”来访问该实例来解析该实例。

The method receives a User instance directly, and no further lookup is necessary. The instance can be resolved by letting Spring MVC convert the path variable into the id type of the domain class first and eventually access the instance through calling findById(…) on the repository instance registered for the domain type.

目前,仓库必须实现 CrudRepository,才有资格转换。

Currently, the repository has to implement CrudRepository to be eligible to be discovered for conversion.

HandlerMethodArgumentResolvers for Pageable and Sort

previous section 中显示的配置片段还注册了一个 PageableHandlerMethodArgumentResolver 和一个 SortHandlerMethodArgumentResolver 的实例。此注册启用 PageableSort 作为有效的控制器方法参数,如以下示例所示:

The configuration snippet shown in the previous section also registers a PageableHandlerMethodArgumentResolver as well as an instance of SortHandlerMethodArgumentResolver. The registration enables Pageable and Sort as valid controller method arguments, as the following example shows:

Using Pageable as a controller method argument
@Controller
@RequestMapping("/users")
class UserController {

  private final UserRepository repository;

  UserController(UserRepository repository) {
    this.repository = repository;
  }

  @RequestMapping
  String showUsers(Model model, Pageable pageable) {

    model.addAttribute("users", repository.findAll(pageable));
    return "users";
  }
}

前面的方法签名导致 Spring MVC 尝试使用以下默认配置从请求参数中派生“Pageable”实例:

The preceding method signature causes Spring MVC try to derive a Pageable instance from the request parameters by using the following default configuration:

Table 1. Request parameters evaluated for Pageable instances

page

Page you want to retrieve. 0-indexed and defaults to 0.

size

Size of the page you want to retrieve. Defaults to 20.

sort

Properties that should be sorted by in the format `property,property(,ASC

为了自定义此行为,请注册一个分别实现“PageableHandlerMethodArgumentResolverCustomizer”接口或“SortHandlerMethodArgumentResolverCustomizer”接口的 bean。调用其“customize()”方法,让你更改设置,如下例所示:

To customize this behavior, register a bean that implements the PageableHandlerMethodArgumentResolverCustomizer interface or the SortHandlerMethodArgumentResolverCustomizer interface, respectively. Its customize() method gets called, letting you change settings, as the following example shows:

@Bean SortHandlerMethodArgumentResolverCustomizer sortCustomizer() {
    return s -> s.setPropertyDelimiter("<-->");
}

如果设置现有“MethodArgumentResolver”的属性不足以满足你的目的,请扩展“SpringDataWebConfiguration”或启用 HATEOAS 的等效项,覆盖“pageableResolver()”或“sortResolver()”方法,并导入你的自定义配置文件,而不是使用“@Enable”注解。

If setting the properties of an existing MethodArgumentResolver is not sufficient for your purpose, extend either SpringDataWebConfiguration or the HATEOAS-enabled equivalent, override the pageableResolver() or sortResolver() methods, and import your customized configuration file instead of using the @Enable annotation.

如果你需要从请求中解析多个“Pageable”或“Sort”实例(例如,对于多个表格),则可以使用 Spring 的“@Qualifier”注解来区分它们。然后,请求参数必须以“${qualifier}_”作为前缀。以下示例显示结果方法签名:

If you need multiple Pageable or Sort instances to be resolved from the request (for multiple tables, for example), you can use Spring’s @Qualifier annotation to distinguish one from another. The request parameters then have to be prefixed with ${qualifier}_. The following example shows the resulting method signature:

String showUsers(Model model,
      @Qualifier("thing1") Pageable first,
      @Qualifier("thing2") Pageable second) { … }

你必须填充“thing1_page”、“thing2_page”等等。

You have to populate thing1_page, thing2_page, and so on.

传递到方法中的默认“Pageable”等效于“PageRequest.of(0, 20)”,但你可以通过在“Pageable”参数上使用“@PageableDefault”注解对其进行自定义。

The default Pageable passed into the method is equivalent to a PageRequest.of(0, 20), but you can customize it by using the @PageableDefault annotation on the Pageable parameter.

Creating JSON representations for Page

对于 Spring MVC 控制器来说,尝试最终向客户端呈现 Spring Data 页面的表示形式是很常见的。虽然人们可以简单地从处理程序方法返回“Page”实例,让 Jackson 按原样呈现它们,但我们强烈建议不要这样做,因为底层实现类“PageImpl”是一个域类型。这意味着我们可能出于无关的原因想要或不得不想更改其 API,并且此类更改可能会以中断的方式改变结果 JSON 表示形式。

It’s common for Spring MVC controllers to try to ultimately render a representation of a Spring Data page to clients. While one could simply return Page instances from handler methods to let Jackson render them as is, we strongly recommend against this as the underlying implementation class PageImpl is a domain type. This means we might want or have to change its API for unrelated reasons, and such changes might alter the resulting JSON representation in a breaking way.

有了 Spring Data 3.1,我们开始通过发出描述该问题的警告日志来暗示这个问题。我们仍然最终建议利用 the integration with Spring HATEOAS 来获得完全稳定且支持超媒体的方式来呈现页面,以便客户端可以轻松地导航。但从版本 3.3 开始,Spring Data 提供了一种方便使用的页面呈现机制,但不需要包含 Spring HATEOAS。

With Spring Data 3.1, we started hinting at the problem by issuing a warning log describing the problem. We still ultimately recommend to leverage the integration with Spring HATEOAS for a fully stable and hypermedia-enabled way of rendering pages that easily allow clients to navigate them. But as of version 3.3 Spring Data ships a page rendering mechanism that is convenient to use but does not require the inclusion of Spring HATEOAS.

Using Spring Data' PagedModel

从本质上讲,该支持包括 Spring HATEOAS 的“PagedModel”的一个简化版本(Spring Data 位于“org.springframework.data.web”包中)。它可用于包装“Page”实例,并产生一个简化表示形式,该表示形式反映了 Spring HATEOAS 确立的结构,但省略了导航链接。

At its core, the support consists of a simplified version of Spring HATEOAS' PagedModel (the Spring Data one located in the org.springframework.data.web package). It can be used to wrap Page instances and result in a simplified representation that reflects the structure established by Spring HATEOAS but omits the navigation links.

import org.springframework.data.web.PagedModel;

@Controller
class MyController {

  private final MyRepository repository;

  // Constructor ommitted

  @GetMapping("/page")
  PagedModel<?> page(Pageable pageable) {
    return new PagedModel<>(repository.findAll(pageable)); (1)
  }
}
1 Wraps the Page instance into a PagedModel.

这将产生如下所示的 JSON 结构:

This will result in a JSON structure looking like this:

{
  "content" : [
     … // Page content rendered here
  ],
  "page" : {
    "size" : 20,
    "totalElements" : 30,
    "totalPages" : 2,
    "number" : 0
  }
}

请注意,该文档包含一个“page”字段,该字段公开基本分页元数据。

Note how the document contains a page field exposing the essential pagination metadata.

Globally enabling simplified Page rendering

如果你不想更改所有现有控制器以添加映射步骤来返回“PagedModel”而不是“Page”,则可以通过调整“@EnableSpringDataWebSupport”来启用将“PageImpl”实例自动转换为“PagedModel”:

If you don’t want to change all your existing controllers to add the mapping step to return PagedModel instead of Page you can enable the automatic translation of PageImpl instances into PagedModel by tweaking @EnableSpringDataWebSupport as follows:

@EnableSpringDataWebSupport(pageSerializationMode = VIA_DTO)
class MyConfiguration { }

这将允许你的控制器仍然返回“Page”实例,并且它们将自动呈现为简化表示形式:

This will allow your controller to still return Page instances and they will automatically be rendered into the simplified representation:

@Controller
class MyController {

  private final MyRepository repository;

  // Constructor ommitted

  @GetMapping("/page")
  Page<?> page(Pageable pageable) {
    return repository.findAll(pageable);
  }
}

Hypermedia Support for Page and Slice

Spring HATEOAS 提供了一个表示模型类(“PagedModel”/“SlicedModel”),它允许使用必要的“Page”/“Slice”元数据以及链接(让客户端可以轻松地浏览页面)来丰富“Page”或“Slice”实例的内容。“Page”到“PagedModel”的转换是由 Spring HATEOAS“RepresentationModelAssembler”接口的实现完成的,称为“PagedResourcesAssembler”。类似地,“Slice”实例可以使用“SlicedResourcesAssembler”转换为“SlicedModel”。以下示例显示如何将“PagedResourcesAssembler”用作控制器方法参数,因为“SlicedResourcesAssembler”的工作方式完全相同:

Spring HATEOAS ships with a representation model class (PagedModel/SlicedModel) that allows enriching the content of a Page or Slice instance with the necessary Page/Slice metadata as well as links to let the clients easily navigate the pages. The conversion of a Page to a PagedModel is done by an implementation of the Spring HATEOAS RepresentationModelAssembler interface, called the PagedResourcesAssembler. Similarly Slice instances can be converted to a SlicedModel using a SlicedResourcesAssembler. The following example shows how to use a PagedResourcesAssembler as a controller method argument, as the SlicedResourcesAssembler works exactly the same:

Using a PagedResourcesAssembler as controller method argument
@Controller
class PersonController {

  private final PersonRepository repository;

  // Constructor omitted

  @GetMapping("/people")
  HttpEntity<PagedModel<Person>> people(Pageable pageable,
    PagedResourcesAssembler assembler) {

    Page<Person> people = repository.findAll(pageable);
    return ResponseEntity.ok(assembler.toModel(people));
  }
}

启用配置,如前面的示例所示,可以让“PagedResourcesAssembler”用作控制器方法参数。对其调用“toModel(…)”有以下影响:

Enabling the configuration, as shown in the preceding example, lets the PagedResourcesAssembler be used as a controller method argument. Calling toModel(…) on it has the following effects:

  • The content of the Page becomes the content of the PagedModel instance.

  • The PagedModel object gets a PageMetadata instance attached, and it is populated with information from the Page and the underlying Pageable.

  • The PagedModel may get prev and next links attached, depending on the page’s state. The links point to the URI to which the method maps. The pagination parameters added to the method match the setup of the PageableHandlerMethodArgumentResolver to make sure the links can be resolved later.

假设我们在数据库中有 30 个 Person 实例。你现在可以触发一个请求 (GET [role="bare"]http://localhost:8080/people),然后看到类似于以下内容的输出:

Assume we have 30 Person instances in the database. You can now trigger a request (GET [role="bare"]http://localhost:8080/people) and see output similar to the following:

{ "links" : [
    { "rel" : "next", "href" : "http://localhost:8080/persons?page=1&size=20" }
  ],
  "content" : [
     … // 20 Person instances rendered here
  ],
  "page" : {
    "size" : 20,
    "totalElements" : 30,
    "totalPages" : 2,
    "number" : 0
  }
}

这里显示的 JSON 封套格式不遵循任何正式指定的结构,并且不能保证其稳定,我们可能会随时更改它。强烈建议启用 Spring HATEOAS 支持的超媒体、官方媒体类型(如 HAL)。可以使用其 @EnableHypermediaSupport 注解激活它们。在 Spring HATEOAS reference documentation 中查找更多信息。

The JSON envelope format shown here doesn’t follow any formally specified structure and it’s not guaranteed stable and we might change it at any time. It’s highly recommended to enable the rendering as a hypermedia-enabled, official media type, supported by Spring HATEOAS, like HAL. Those can be activated by using its @EnableHypermediaSupport annotation. Find more information in the Spring HATEOAS reference documentation.

该汇编器生成了正确的 URI,并且还采用了默认配置将参数解析成“Pageable”以用于即将到来的请求。这意味着,如果你更改该配置,链接将自动遵循更改。默认情况下,该汇编器指向调用它的控制器方法,但你可以通过传递一个自定义的“Link”作为构建分页链接的基础来对其进行自定义,这会重载“PagedResourcesAssembler.toModel(…)”方法。

The assembler produced the correct URI and also picked up the default configuration to resolve the parameters into a Pageable for an upcoming request. This means that, if you change that configuration, the links automatically adhere to the change. By default, the assembler points to the controller method it was invoked in, but you can customize that by passing a custom Link to be used as base to build the pagination links, which overloads the PagedResourcesAssembler.toModel(…) method.

Spring Data Jackson Modules

核心模块以及一些特定于存储的模块随用于 Spring Data 域的类型(如 org.springframework.data.geo.Distanceorg.springframework.data.geo.Point)的一组 Jackson 模块一起提供。一旦启用 web support 且获得 com.fasterxml.jackson.databind.ObjectMapper 时,便会导入这些模块。

The core module, and some of the store specific ones, ship with a set of Jackson Modules for types, like org.springframework.data.geo.Distance and org.springframework.data.geo.Point, used by the Spring Data domain. Those Modules are imported once web support is enabled and com.fasterxml.jackson.databind.ObjectMapper is available.

在初始化期间,SpringDataJacksonModules(如 SpringDataJacksonConfiguration)将被基础架构选中,以便声明的 com.fasterxml.jackson.databind.Module 可供 Jackson ObjectMapper 使用。

During initialization SpringDataJacksonModules, like the SpringDataJacksonConfiguration, get picked up by the infrastructure, so that the declared com.fasterxml.jackson.databind.Module`s are made available to the Jackson `ObjectMapper.

常见的基础架构为以下域类型注册了数据绑定混入。

Data binding mixins for the following domain types are registered by the common infrastructure.

org.springframework.data.geo.Distance
org.springframework.data.geo.Point
org.springframework.data.geo.Box
org.springframework.data.geo.Circle
org.springframework.data.geo.Polygon

各个模块可能提供其他 SpringDataJacksonModules。有关更多详细信息,请参阅特定存储部分。

The individual module may provide additional SpringDataJacksonModules. Please refer to the store specific section for more details.

Web Databinding Support

您可以使用 Spring Data 预测(在 Projections 中描述)通过使用 JSONPath 表达式(需要 Jayway JsonPath)或 XPath 表达式(需要 XmlBeam)来绑定传入请求有效负载,如以下示例所示:

You can use Spring Data projections (described in Projections) to bind incoming request payloads by using either JSONPath expressions (requires Jayway JsonPath) or XPath expressions (requires XmlBeam), as the following example shows:

HTTP payload binding using JSONPath or XPath expressions
@ProjectedPayload
public interface UserPayload {

  @XBRead("//firstname")
  @JsonPath("$..firstname")
  String getFirstname();

  @XBRead("/lastname")
  @JsonPath({ "$.lastname", "$.user.lastname" })
  String getLastname();
}

您可以将前一个示例中所示的类型用作 Spring MVC 处理程序方法参数,或在 RestTemplate 方法之一上使用 ParameterizedTypeReference。前述方法声明将尝试在给定文档中的任何位置查找 firstnamelastname XML 查找在传入文档的顶级上执行。该 JSON 变体首先尝试顶级 lastname,但如果前者未返回任何值,它还会尝试嵌套在 user 子文档中的 lastname。这种方式可以轻松缓解源文档的结构变化,而无需客户端调用公开的方法(通常是基于类的有效负载绑定的缺点)。

You can use the type shown in the preceding example as a Spring MVC handler method argument or by using ParameterizedTypeReference on one of methods of the RestTemplate. The preceding method declarations would try to find firstname anywhere in the given document. The lastname XML lookup is performed on the top-level of the incoming document. The JSON variant of that tries a top-level lastname first but also tries lastname nested in a user sub-document if the former does not return a value. That way, changes in the structure of the source document can be mitigated easily without having clients calling the exposed methods (usually a drawback of class-based payload binding).

嵌套投影受支持,如 Projections 中所述。如果该方法返回一个复杂的非接口类型,则 Jackson ObjectMapper 用于映射最终值。

Nested projections are supported as described in Projections. If the method returns a complex, non-interface type, a Jackson ObjectMapper is used to map the final value.

对于 Spring MVC,只要 @EnableSpringDataWebSupport 处于活动状态且类路径中存在所需依赖项,就会自动注册必要的转换器。如需与 RestTemplate 配合使用,请手动注册 ProjectingJackson2HttpMessageConverter(JSON)或 XmlBeamHttpMessageConverter

For Spring MVC, the necessary converters are registered automatically as soon as @EnableSpringDataWebSupport is active and the required dependencies are available on the classpath. For usage with RestTemplate, register a ProjectingJackson2HttpMessageConverter (JSON) or XmlBeamHttpMessageConverter manually.

有关更多信息,请参阅授权 Spring Data Examples repository 中的 web projection example

For more information, see the web projection example in the canonical Spring Data Examples repository.

Querydsl Web Support

对于那些具有 QueryDSL 集成的存储,您可以从 Request 查询字符串中包含的属性中派生查询。

For those stores that have QueryDSL integration, you can derive queries from the attributes contained in a Request query string.

请考虑以下查询字符串:

Consider the following query string:

?firstname=Dave&lastname=Matthews

鉴于来自上一个示例的 User 对象,您可以使用 QuerydslPredicateArgumentResolver 将查询字符串解析为以下值,如下所示:

Given the User object from the previous examples, you can resolve a query string to the following value by using the QuerydslPredicateArgumentResolver, as follows:

QUser.user.firstname.eq("Dave").and(QUser.user.lastname.eq("Matthews"))

当 classpath 中找到 Querydsl 时,将自动启用此功能,并启用 @EnableSpringDataWebSupport

The feature is automatically enabled, along with @EnableSpringDataWebSupport, when Querydsl is found on the classpath.

向方法签名中添加 @QuerydslPredicate 提供一个现成的 Predicate,您可以使用 QuerydslPredicateExecutor 运行该 Predicate

Adding a @QuerydslPredicate to the method signature provides a ready-to-use Predicate, which you can run by using the QuerydslPredicateExecutor.

类型信息通常从方法的返回类型解析。由于该信息不一定与域类型匹配,因此,最好使用 QuerydslPredicateroot 属性。

Type information is typically resolved from the method’s return type. Since that information does not necessarily match the domain type, it might be a good idea to use the root attribute of QuerydslPredicate.

以下示例演示如何在方法签名中使用 @QuerydslPredicate

The following example shows how to use @QuerydslPredicate in a method signature:

@Controller
class UserController {

  @Autowired UserRepository repository;

  @RequestMapping(value = "/", method = RequestMethod.GET)
  String index(Model model, @QuerydslPredicate(root = User.class) Predicate predicate,    1
          Pageable pageable, @RequestParam MultiValueMap<String, String> parameters) {

    model.addAttribute("users", repository.findAll(predicate, pageable));

    return "index";
  }
}
1 Resolve query string arguments to matching Predicate for User.

默认绑定如下:

The default binding is as follows:

  • Object on simple properties as eq.

  • Object on collection like properties as contains.

  • Collection on simple properties as in.

您可以通过 @QuerydslPredicatebindings 属性来自定这些绑定,或通过使用 Java 8 default methods 并向存储库接口添加 QuerydslBinderCustomizer 方法来自定这些绑定,如下所示:

You can customize those bindings through the bindings attribute of @QuerydslPredicate or by making use of Java 8 default methods and adding the QuerydslBinderCustomizer method to the repository interface, as follows:

interface UserRepository extends CrudRepository<User, String>,
                                 QuerydslPredicateExecutor<User>,                1
                                 QuerydslBinderCustomizer<QUser> {               2

  @Override
  default void customize(QuerydslBindings bindings, QUser user) {

    bindings.bind(user.username).first((path, value) -> path.contains(value))    3
    bindings.bind(String.class)
      .first((StringPath path, String value) -> path.containsIgnoreCase(value)); 4
    bindings.excluding(user.password);                                           5
  }
}
1 QuerydslPredicateExecutor provides access to specific finder methods for Predicate.
2 QuerydslBinderCustomizer defined on the repository interface is automatically picked up and shortcuts @QuerydslPredicate(bindings=…​).
3 Define the binding for the username property to be a simple contains binding.
4 Define the default binding for String properties to be a case-insensitive contains match.
5 Exclude the password property from Predicate resolution.

您可以在从存储库或 @QuerydslPredicate 应用特定绑定前,注册保存默认 Querydsl 绑定的 QuerydslBinderCustomizerDefaults bean。

You can register a QuerydslBinderCustomizerDefaults bean holding default Querydsl bindings before applying specific bindings from the repository or @QuerydslPredicate.

Repository Populators

如果您使用 Spring JDBC 模块,您可能熟悉利用 SQL 脚本填充 DataSource 的支持。存储库级别上提供类似的抽象,尽管它未使用 SQL 作为数据定义语言,因为它必须独立于存储。因此,填充器支持 XML(通过 Spring 的 OXM 抽象)和 JSON(通过 Jackson)定义填充存储库的数据。

If you work with the Spring JDBC module, you are probably familiar with the support for populating a DataSource with SQL scripts. A similar abstraction is available on the repositories level, although it does not use SQL as the data definition language because it must be store-independent. Thus, the populators support XML (through Spring’s OXM abstraction) and JSON (through Jackson) to define data with which to populate the repositories.

假设您有一个名为 data.json 的文件,内容如下:

Assume you have a file called data.json with the following content:

Data defined in JSON
[ { "_class" : "com.acme.Person",
 "firstname" : "Dave",
  "lastname" : "Matthews" },
  { "_class" : "com.acme.Person",
 "firstname" : "Carter",
  "lastname" : "Beauford" } ]

您可以使用 Spring Data Commons 中提供的存储库命名空间的填充器元素填充您的存储库。要将前述数据填充到您的 PersonRepository 中,请声明类似于以下内容的填充器:

You can populate your repositories by using the populator elements of the repository namespace provided in Spring Data Commons. To populate the preceding data to your PersonRepository, declare a populator similar to the following:

Declaring a Jackson repository populator
<?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:repository="http://www.springframework.org/schema/data/repository"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
    https://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/data/repository
    https://www.springframework.org/schema/data/repository/spring-repository.xsd">

  <repository:jackson2-populator locations="classpath:data.json" />

</beans>

以上声明将导致读取 data.json 文件并由 Jackson ObjectMapper 反序列化该文件。

The preceding declaration causes the data.json file to be read and deserialized by a Jackson ObjectMapper.

反序列化 JSON 对象的类型由检查 JSON 文档中的 _class 属性决定。基础架构最终会选择适当的存储库为已反序列化的对象处理。

The type to which the JSON object is unmarshalled is determined by inspecting the _class attribute of the JSON document. The infrastructure eventually selects the appropriate repository to handle the object that was deserialized.

要使用 XML 定义数据,以便刷新那些存储库,您可以使用 unmarshaller-populator 元素。您可以将其配置为使用 Spring OXM 中的一个 XML 转换器选项。有关详细信息,请参阅 {spring-framework-docs}/data-access/oxm.html[Spring 参考手册]。以下示例显示了如何用 JAXB 反组装一个存储库填充器:

To instead use XML to define the data the repositories should be populated with, you can use the unmarshaller-populator element. You configure it to use one of the XML marshaller options available in Spring OXM. See the {spring-framework-docs}/data-access/oxm.html[Spring reference documentation] for details. The following example shows how to unmarshall a repository populator with JAXB:

Declaring an unmarshalling repository populator (using JAXB)
<?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:repository="http://www.springframework.org/schema/data/repository"
  xmlns:oxm="http://www.springframework.org/schema/oxm"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
    https://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/data/repository
    https://www.springframework.org/schema/data/repository/spring-repository.xsd
    http://www.springframework.org/schema/oxm
    https://www.springframework.org/schema/oxm/spring-oxm.xsd">

  <repository:unmarshaller-populator locations="classpath:data.json"
    unmarshaller-ref="unmarshaller" />

  <oxm:jaxb2-marshaller contextPath="com.acme" />

</beans>