1. 概述
Spring for GraphQL 为基于GraphQL Java 构建的 Spring 应用程序提供支持。这是 GraphQL Java 团队和 Spring 工程。
Spring for GraphQL 是GraphQL Java Spring项目的继承者,来自 GraphQL Java 团队。它的目标是成为所有 Spring、GraphQL 应用程序的基础。
请使用我们的问题跟踪器报告问题、讨论设计问题或请求功能。
请参阅我们的维基。 了解新增功能、基线要求、升级说明以及其他跨版本信息。
要开始使用,请查看 Spring GraphQL 入门on start.spring.io和Samples。
2. 服务器传输
Spring for GraphQL 支持服务器通过 HTTP、WebSocket 和 RSocket。
2.1. HTTP
GraphQlHttpHandler
通过 HTTP 请求处理 GraphQL 并委托给拦截链以执行请求。有两种变体,一种用于 Spring MVC 和一个用于 Spring WebFlux 的 MVC。两者都异步处理请求,并且具有 等效的功能,但分别依赖于阻塞和非阻塞 I/O 编写 HTTP 响应。
请求必须使用 HTTP POST,其中 GraphQL 请求详细信息作为 JSON 包含在 请求正文,如提议的GraphQL over HTTP规范中所定义。成功解码 JSON 正文后,HTTP 响应 状态始终为 200(正常),并且 GraphQL 请求执行中的任何错误都显示在 GraphQL 响应的“错误”部分。媒体类型的默认和首选选择是,但也受支持,如中所述 规范。"application/graphql+json"
"application/json"
GraphQlHttpHandler
可以通过声明 abean 并使用 Spring MVC 或 WebFlux 创建路由来公开为 HTTP 端点。这 启动启动器执行此操作,请参阅Web 终结点部分 实际配置的详细信息或检查包含的内容。RouterFunction
RouterFunctions
GraphQlWebMvcAutoConfiguration
GraphQlWebFluxAutoConfiguration
Spring for GraphQL 存储库包含一个 Spring MVCHTTP 示例应用程序。
2.2. 网络套接字
GraphQlWebSocketHandler
根据graphql-ws库中定义的协议处理 WebSocket 上的 GraphQL 请求。使用的主要原因 GraphQL over WebSocket 是允许发送 GraphQL 流的订阅。 响应,但它也可以用于具有单个响应的常规查询。 处理程序将每个请求委托给拦截链,以便进一步 请求执行。
GraphQL over WebSocket Protocol 有两个这样的协议,一个在subscriptions-transport-ws库中,另一个在graphql-ws库中。前者不活跃且 后者继任。阅读这篇博文了解历史。 |
有两种变体,一种用于Spring MVC,一种用于 Spring WebFlux.两者都异步处理请求,并具有等效的功能。 WebFlux 处理程序还使用非阻塞 I/O 和背压来流式传输消息, 这很好用,因为在 GraphQL Java 中,订阅响应是反应式流。GraphQlWebSocketHandler
Publisher
该项目列出了许多供客户使用的配方。graphql-ws
GraphQlWebSocketHandler
可以通过声明 abean 并使用它来将处理程序映射到 URL 路径,将其公开为 WebSocket 终结点。默认情况下, 启动启动器不会通过 WebSocket 端点公开 GraphQL,但很容易 通过为终结点路径添加属性来启用它。有关详细信息,请参阅Web 端点部分,或查看实际的启动启动器配置。SimpleUrlHandlerMapping
GraphQlWebMvcAutoConfiguration
GraphQlWebFluxAutoConfiguration
Spring for GraphQL 存储库包含一个WebFlux WebSocket 示例应用程序。
2.3. RSocket
GraphQlRSocketHandler
通过 RSocket 请求处理 GraphQL。查询和突变是 预期并作为 RSocket 交互处理,而订阅 处理为。request-response
request-stream
GraphQlRSocketHandler
可以使用映射到的 ana 中的委托 GraphQL 请求的路由。例如:@Controller
@Controller
public class GraphQlRSocketController {
private final GraphQlRSocketHandler handler;
GraphQlRSocketController(GraphQlRSocketHandler handler) {
this.handler = handler;
}
@MessageMapping("graphql")
public Mono<Map<String, Object>> handle(Map<String, Object> payload) {
return this.handler.handle(payload);
}
@MessageMapping("graphql")
public Flux<Map<String, Object>> handleSubscription(Map<String, Object> payload) {
return this.handler.handleSubscription(payload);
}
}
2.4. 拦截
服务器传输允许在 GraphQL Java 引擎之前和之后拦截请求 调用以处理请求。
2.4.1. WebGraphQlInterceptor
HTTP和WebSocket传输调用链 0 或更多,后跟一个调用 GraphQL Java 引擎允许应用程序拦截 传入请求,然后执行以下操作之一:WebGraphQlInterceptor
ExecutionGraphQlService
WebGraphQlInterceptor
- 检查 HTTP 请求详细信息
- 自定义
graphql.ExecutionInput
- 添加 HTTP 响应标头
- 自定义
graphql.ExecutionResult
例如,拦截器可以将 HTTP 请求标头传递给:DataFetcher
class HeaderInterceptor implements WebGraphQlInterceptor {
@Override
public Mono<WebGraphQlResponse> intercept(WebGraphQlRequest request, Chain chain) {
String value = request.getHeaders().getFirst("myHeader");
request.configureExecutionInput((executionInput, builder) ->
builder.graphQLContext(Collections.singletonMap("myHeader", value)).build());
return chain.next(request);
}
}
@Controller
class MyController {
@QueryMapping
Person person(@ContextValue String myHeader) {
// ...
}
}
拦截器将 HTTP 请求标头值添加到 GraphQLContext 中 |
数据控制器方法访问值 |
相反,拦截器可以访问控制器添加到的值:GraphQLContext
@Controller
class MyController {
@QueryMapping
Person person(GraphQLContext context) {
context.put("cookieName", "123");
}
}
// Subsequent access from a WebGraphQlInterceptor
class HeaderInterceptor implements WebGraphQlInterceptor {
@Override
public Mono<WebGraphQlResponse> intercept(WebGraphQlRequest request, Chain chain) {
return chain.next(request).doOnNext(response -> {
String value = response.getExecutionInput().getGraphQLContext().get("cookieName");
ResponseCookie cookie = ResponseCookie.from("cookieName", value).build();
response.getResponseHeaders().add(HttpHeaders.SET_COOKIE, cookie.toString());
});
}
}
控制器为 |
拦截器使用该值添加 HTTP 响应标头 |
WebGraphQlHandler
可以修改,例如,检查和修改 请求验证错误,这些错误在执行开始之前引发,并且不能 处理方式为:ExecutionResult
DataFetcherExceptionResolver
static class RequestErrorInterceptor implements WebGraphQlInterceptor {
@Override
public Mono<WebGraphQlResponse> intercept(WebGraphQlRequest request, Chain chain) {
return chain.next(request).map(response -> {
if (response.isValid()) {
return response;
}
List<GraphQLError> errors = response.getErrors().stream()
.map(error -> {
GraphqlErrorBuilder<?> builder = GraphqlErrorBuilder.newError();
// ...
return builder.build();
})
.collect(Collectors.toList());
return response.transform(builder -> builder.errors(errors).build());
});
}
}
返回相同的 ifhas 具有非空值的“data”键 |
检查并转换 GraphQL 错误 |
更新修改后的错误 |
用于配置链。这是支持的 通过启动启动器,请参阅Web 终结点。WebGraphQlHandler
WebGraphQlInterceptor
2.4.2. RSocketQlInterceptor
与WebGraphQlInterceptor类似,允许拦截 GraphQL 在 GraphQL Java 引擎执行之前和之后通过 RSocket 请求。您可以使用 这要定制和的。RSocketQlInterceptor
graphql.ExecutionInput
graphql.ExecutionResult
3. 请求执行
ExecutionGraphQlService
是调用 GraphQL Java 来执行的主要 Spring 抽象 请求。基础传输(如服务器传输)委托 toto 处理请求。ExecutionGraphQlService
主实现配置了对要调用的实例的 afor 访问。DefaultExecutionGraphQlService
GraphQlSource
graphql.GraphQL
3.1. GraphQLSource
GraphQlSource
是一个合约,用于公开实例以使用它 包括用于构建该实例的构建器 API。默认构建器可通过 a 使用。Spring 引导启动器创建 此生成器并进一步初始化它,如下所示:graphql.GraphQL
GraphQlSource.schemaResourceBuilder()
- 从可配置位置加载架构文件。
- 公开适用于的属性。GraphQlSource.Builder
- 检测运行时布线配置器bean。
- 检测GraphQL 指标的检测 bean。
- 检测 bean 以解决异常。DataFetcherExceptionResolver
- 检测订阅异常解析。
SubscriptionExceptionResolver
对于进一步的自定义,您可以声明 abean。例如,到 配置您自己的:GraphQlSourceBuilderCustomizer
ExecutionIdProvider
@Configuration(proxyBeanMethods = false)
class GraphQlConfig {
@Bean
public GraphQlSourceBuilderCustomizer sourceBuilderCustomizer() {
return (builder) ->
builder.configureGraphQl(graphQlBuilder ->
graphQlBuilder.executionIdProvider(new CustomExecutionIdProvider()));
}
}
3.1.1. 模式资源
GraphQlSource.Builder
可以配置一个或多个实例 解析并合并在一起。这意味着架构文件可以从几乎任何 位置。Resource
默认情况下,Spring 引导启动器会查找带有扩展名的模式文件 位置下的“.graphqls”或“.gqls”,这是典型的。您还可以使用文件系统位置或任何位置 由 Springhierarchy 支持,包括一个自定义实现 从远程位置、存储或内存加载架构文件。classpath:graphql/**
src/main/resources/graphql
Resource
用于跨多个类路径查找架构文件 位置,例如跨多个模块。 |
3.1.2. 模式创建
默认情况下,使用 GraphQL Java 来创建。这适用于典型用途,但如果您需要使用 不同的生成器,例如对于联合,您可以注册回调:GraphQlSource.Builder
SchemaGenerator
graphql.schema.GraphQLSchema
schemaFactory
GraphQlSource.Builder builder = ...
builder.schemaResources(..)
.configureRuntimeWiring(..)
.schemaFactory((typeDefinitionRegistry, runtimeWiring) -> {
// create GraphQLSchema
})
GraphQlSource部分解释了如何使用Spring Boot进行配置。
3.1.3. 模式遍历
如果您想在之后遍历架构,您可以注册 aviaif 它已创建,并可能将更改应用于。请记住, 但是,此类访问者无法更改架构。如果需要对架构进行更改,请参阅架构转换。graphql.schema.GraphQLTypeVisitor
builder.schemaResources(..).typeVisitors(..)
GraphQLCodeRegistry
3.1.4. 模式转换
您可以注册 aviaif 如果您想遍历 并在创建架构后对其进行转换,并对架构进行更改。谨记 这通常比架构遍历更昂贵 首选遍历而不是转换,除非需要进行架构更改。graphql.schema.GraphQLTypeVisitor
builder.schemaResources(..).typeVisitorsToTransformSchema(..)
3.1.5. RuntimeWiringConfigurer
您可以使用注册:RuntimeWiringConfigurer
- 自定义标量类型。
- 处理代码的指令。
-
TypeResolver
,如果需要覆盖某个类型的默认类型解析程序。 -
DataFetcher
对于一个字段,尽管大多数应用程序将简单地配置,以检测带注释的处理程序方法。 弹簧引导启动器添加默认情况下。AnnotatedControllerConfigurer
DataFetcher
AnnotatedControllerConfigurer
与 Web 框架不同,GraphQL 不使用 Jackson 注释来驱动 JSON 序列化/反序列化。 自定义数据类型及其序列化必须描述为标量。 |
Spring 引导启动器检测类型和 将它们注册在。这意味着在大多数情况下,您将拥有 配置中类似于以下内容的内容:RuntimeWiringConfigurer
GraphQlSource.Builder
@Configuration
public class GraphQlConfig {
@Bean
public RuntimeWiringConfigurer runtimeWiringConfigurer(BookRepository repository) {
GraphQLScalarType scalarType = ... ;
SchemaDirectiveWiring directiveWiring = ... ;
DataFetcher dataFetcher = QuerydslDataFetcher.builder(repository).single();
return wiringBuilder -> wiringBuilder
.scalar(scalarType)
.directiveWiring(directiveWiring)
.type("Query", builder -> builder.dataFetcher("book", dataFetcher));
}
}
如果您需要添加 a,例如进行考虑到 架构定义,实现同时接受 THE 和 输出的替代方法。这允许您添加任何 然后按顺序调用的工厂数。WiringFactory
configure
RuntimeWiring.Builder
List<WiringFactory>
3.1.6. 默认值TypeResolver
GraphQlSource.Builder
registersas defaultto 用于尚未具有此类注册的 GraphQL 接口和联合 通过运行时布线配置器。目的 ain GraphQL Java 是确定值的 GraphQL 对象类型 从 for GraphQL 接口或联合字段返回。ClassNameTypeResolver
TypeResolver
TypeResolver
DataFetcher
ClassNameTypeResolver
尝试将值的简单类名与 GraphQL 匹配 对象类型,如果不成功,它还导航其超类型,包括 基类和接口,查找匹配项。提供 选项以配置名称提取函数以及 GraphQL 对象类型 名称映射,应有助于涵盖更多极端情况:ClassNameTypeResolver
Class
GraphQlSource.Builder builder = ...
ClassNameTypeResolver classNameTypeResolver = new ClassNameTypeResolver();
classNameTypeResolver.setClassNameExtractor((klass) -> {
// Implement Custom ClassName Extractor here
});
builder.defaultTypeResolver(classNameTypeResolver);
GraphQlSource部分解释了如何使用Spring Boot进行配置。
3.1.7. 操作缓存
GraphQL Java 必须在执行操作之前对其进行解析和验证。这可能会影响 性能显著。为了避免需要重新分析和验证,应用程序可以 配置缓存和重用文档实例。GraphQL Java 文档提供了更多关于 通过 A 进行查询缓存。PreparsedDocumentProvider
PreparsedDocumentProvider
在Spring GraphQL中,你可以通过以下方式注册: .PreparsedDocumentProvider
GraphQlSource.Builder#configureGraphQl
// Typically, accessed through Spring Boot's GraphQlSourceBuilderCustomizer
GraphQlSource.Builder builder = ...
// Create provider
PreparsedDocumentProvider provider = ...
builder.schemaResources(..)
.configureRuntimeWiring(..)
.configureGraphQl(graphQLBuilder -> graphQLBuilder.preparsedDocumentProvider(provider))
GraphQlSource部分解释了如何使用Spring Boot进行配置。
3.1.8. 指令
GraphQL 语言支持“描述备用运行时执行和 GraphQL 文档中的类型验证行为”。指令类似于 中的注释 Java 但在 GraphQL 文档中对类型、字段、片段和操作声明。
GraphQL Java 提供合约来帮助应用程序检测 并处理指令。有关更多详细信息,请参阅 GraphQL Java 文档。SchemaDirectiveWiring
在Spring GraphQL中,你可以通过RuntimeWiringConfigurer注册。弹簧启动启动器检测到 这样的豆子,所以你可能会有这样的东西:SchemaDirectiveWiring
@Configuration
public class GraphQlConfig {
@Bean
public RuntimeWiringConfigurer runtimeWiringConfigurer() {
return builder -> builder.directiveWiring(new MySchemaDirectiveWiring());
}
}
有关指令支持的示例,请查看Extended Validation for Graphql Java库。 |
3.2. 反应式DataFetcher
默认构建器启用对 ato 返回器的支持,它使这些内容适应聚合值 并转换为列表,除非请求是 GraphQL 订阅请求, 在这种情况下,返回值仍然是 反应式流用于流式处理 GraphQL 响应。GraphQlSource
DataFetcher
Mono
Flux
CompletableFuture
Flux
Publisher
反应式可以依赖于对从 传输层,例如来自 WebFlux 请求处理,请参阅WebFlux 上下文。DataFetcher
3.3. 上下文传播
Spring for GraphQL 支持通过 GraphQL Java 透明地传播来自服务器传输的上下文,以及它和其他组件 调用。这包括来自Spring MVC请求处理的两个上下文 线程和反应器来自 WebFlux 处理管道。DataFetcher
ThreadLocal
Context
3.3.1. 网络媒体
A和 GraphQL Java 调用的其他组件可能并不总是在 与Spring MVC处理程序相同的线程,例如,如果异步WebGraphQlInterceptor或切换到 不同的线程。DataFetcher
DataFetcher
Spring for GraphQL 支持从 Servlet 容器传播值 线程到线程 a 和 GraphQL Java 调用的其他组件到 继续执行。为此,应用程序需要实现感兴趣的值:ThreadLocal
DataFetcher
io.micrometer.context.ThreadLocalAccessor
ThreadLocal
public class RequestAttributesAccessor implements ThreadLocalAccessor<RequestAttributes> {
@Override
public Object key() {
return RequestAttributesAccessor.class.getName();
}
@Override
public RequestAttributes getValue() {
return RequestContextHolder.getRequestAttributes();
}
@Override
public void setValue(RequestAttributes attributes) {
RequestContextHolder.setRequestAttributes(attributes);
}
@Override
public void reset() {
RequestContextHolder.resetRequestAttributes();
}
}
您可以在启动时手动注册全局实例,该实例可通过 a 访问。您也可以注册 自动通过机制。ThreadLocalAccessor
ContextRegistry
io.micrometer.context.ContextRegistry#getInstance()
java.util.ServiceLoader
3.3.2. 网络通量
响应式数据获取器可以依赖于对反应器上下文的访问,该上下文 源自 WebFlux 请求处理链。这包括反应器上下文 由WebGraphQlInterceptor组件添加。
3.4. 异常解决
一个 GraphQL Java 应用程序可以注册 ato 来决定如何 表示 GraphQL 响应的“错误”部分中数据层的异常。DataFetcherExceptionHandler
Spring for GraphQL 有一个内置的,配置为使用 默认的GraphQLSource构建器。它允许应用程序注册 按顺序调用的一个或多个 Spring组件 直到解析为(可能为空的)对象列表。DataFetcherExceptionHandler
DataFetcherExceptionResolver
Exception
graphql.GraphQLError
DataFetcherExceptionResolver
是一个异步合约。对于大多数实现,它 将足以扩展和覆盖 它的方法之一 同步解决异常。DataFetcherExceptionResolverAdapter
resolveToSingleError
resolveToMultipleErrors
A可以通过以下方式分配到类别。 在Spring GraphQL中,您还可以分配viawhich具有以下常见 应用程序可用于对错误进行分类的分类:GraphQLError
graphql.ErrorClassification
ErrorType
-
BAD_REQUEST
-
UNAUTHORIZED
-
FORBIDDEN
-
NOT_FOUND
-
INTERNAL_ERROR
如果异常仍未解决,则默认情况下,它被归类为包含类别名称和发件人的通用消息。消息故意不透明以避免泄漏 实现详细信息。应用程序可以使用a来自定义 错误详细信息。INTERNAL_ERROR
executionId
DataFetchingEnvironment
DataFetcherExceptionResolver
未解决的异常记录在错误级别以及关联 发送到客户端的错误。已解决的异常记录在调试级别。executionId
3.4.1. 请求异常
GraphQL Java 引擎在解析请求时可能会遇到验证或其他错误 这反过来又会阻止请求执行。在这种情况下,响应包含 “data”键和一个或多个全局的请求级“错误”,即不是 具有字段路径。null
DataFetcherExceptionResolver
无法处理此类全局错误,因为它们被引发 在执行开始之前和调用 anyis 之前。应用程序可以使用 传输级拦截器来检查和转换错误。 请参阅WebGraphQlInterceptor 下的示例。DataFetcher
ExecutionResult
3.4.2. 订阅例外
对于订阅请求可能会以错误信号完成,在这种情况下 底层传输(例如 WebSocket)发送带有列表的最终“错误”类型消息 的 GraphQL 错误。Publisher
DataFetcherExceptionResolver
无法解决订阅中的错误, 由于数据仅创建初始。之后, 传输订阅,然后可能会完成并显示错误。Publisher
DataFetcher
Publisher
Publisher
应用程序可以注册以解析 订阅中的异常为了将这些异常解析为 GraphQL 错误 以发送到客户端。SubscriptionExceptionResolver
Publisher
3.5. 批量加载
给定它,我们可以为一本书创建一个,另一个 为其作者。这允许选择有或没有作者的书籍,但这意味着书籍 并且作者没有一起加载,这在查询多个时效率特别低下 作为每本书作者的书籍是单独加载的。这称为 N+1 选择 问题。Book
Author
DataFetcher
3.5.1. DataLoader
GraphQL Java 提供了一种批量加载相关实体的机制。 您可以在GraphQL Java 文档中找到完整的详细信息。下面是一个 工作原理摘要:DataLoader
- 注册在可以加载实体,给定唯一键。
DataLoader
DataLoaderRegistry
-
DataFetcher
可以访问并使用它们按 ID 加载实体。DataLoader
- 通过返回未来来延迟加载,以便可以批量完成。
DataLoader
-
DataLoader
维护已加载实体的每请求缓存,这些缓存可以进一步 提高效率。
3.5.2. BatchLoaderRegistry
GraphQL Java 中的完整批处理加载机制需要实现以下之一 几个接口,然后包装和注册那些屁股 有一个名字在。BatchLoader
DataLoader
DataLoaderRegistry
Spring GraphQL 中的 API 略有不同。对于注册,只有一个, 集中公开工厂方法和构建器来创建和 注册任意数量的批量加载函数:BatchLoaderRegistry
@Configuration
public class MyConfig {
public MyConfig(BatchLoaderRegistry registry) {
registry.forTypePair(Long.class, Author.class).registerMappedBatchLoader((authorIds, env) -> {
// return Mono<Map<Long, Author>
});
// more registrations ...
}
}
Spring Boot 启动器声明了您可以注入的 abean 您的配置,如上所示,或按顺序放入任何组件(如控制器) 注册批量加载函数。反过来,注入到确保每个请求注册的地方。BatchLoaderRegistry
BatchLoaderRegistry
DefaultExecutionGraphQlService
DataLoader
默认情况下,名称基于目标实体的类名。 这允许方法使用泛型类型声明DataLoader 参数,并且 无需指定名称。但是,如有必要,可以通过构建器以及其他名称自定义名称。DataLoader
@SchemaMapping
BatchLoaderRegistry
DataLoaderOptions
配置默认全局,用作任何 注册,你可以覆盖 Boot'sbean 并使用构造函数 为此接受。DataLoaderOptions
BatchLoaderRegistry
DefaultBatchLoaderRegistry
Supplier<DataLoaderOptions>
在许多情况下,在加载相关实体时,可以使用@BatchMapping控制器方法,这是一种快捷方式 对于和替换需要使用和直接。BatchLoaderRegistry
DataLoader
BatchLoaderRegistry
还提供其他重要的好处。它支持访问 从批量加载函数和 from 方法相同, 以及确保上下文传播到它们。这就是为什么需要应用程序的原因 来使用它。可以直接执行自己的注册,但 此类注册将放弃上述好处。GraphQLContext
@BatchMapping
DataLoader
3.5.3. 测试批量加载
首先在以下设备上执行注册:BatchLoaderRegistry
DataLoaderRegistry
BatchLoaderRegistry batchLoaderRegistry = new DefaultBatchLoaderRegistry();
// perform registrations...
DataLoaderRegistry dataLoaderRegistry = DataLoaderRegistry.newRegistry().build();
batchLoaderRegistry.registerDataLoaders(dataLoaderRegistry, graphQLContext);
现在,您可以按如下方式访问和测试个人:DataLoader
DataLoader<Long, Book> loader = dataLoaderRegistry.getDataLoader(Book.class.getName());
loader.load(1L);
loader.loadMany(Arrays.asList(2L, 3L));
List<Book> books = loader.dispatchAndJoin(); // actual loading
assertThat(books).hasSize(3);
assertThat(books.get(0).getName()).isEqualTo("...");
// ...
4. 数据集成
Spring for GraphQL 允许您利用现有的 Spring 技术,遵循常见的 编程模型以通过 GraphQL 公开底层数据源。
本节讨论 Spring Data 的集成层,该集成层提供了一种简单的方法来 将 Querydsl 或按示例查询的存储库调整为 a,包括 用于自动检测和 GraphQL 查询注册的选项,用于标记的存储库 跟。DataFetcher
@GraphQlRepository
4.1. 查询
Spring for GraphQL 支持使用Querydsl通过 SpringData Querydsl扩展。 Querydsl 提供了一种灵活但类型安全的方法来表达查询谓词: 使用注释处理器生成元模型。
例如,将存储库声明为:QuerydslPredicateExecutor
public interface AccountRepository extends Repository<Account, Long>,
QuerydslPredicateExecutor<Account> {
}
然后使用它来创建:DataFetcher
// For single result queries
DataFetcher<Account> dataFetcher =
QuerydslDataFetcher.builder(repository).single();
// For multi-result queries
DataFetcher<Iterable<Account>> dataFetcher =
QuerydslDataFetcher.builder(repository).many();
您现在可以通过运行时布线配置器注册上述内容。DataFetcher
构建一个 Querydslfrom GraphQL 请求参数,以及 使用它来获取数据。Spring Data 支持 JPA, MongoDB和LDAP。DataFetcher
Predicate
QuerydslPredicateExecutor
如果存储库是,则构建器返回 sor。Spring Data支持这一点 MongoDB的变体。ReactiveQuerydslPredicateExecutor
DataFetcher<Mono<Account>>
DataFetcher<Flux<Account>>
4.1.1. 构建设置
要在构建中配置 Querydsl,请遵循官方参考文档:
例如:
格拉德尔
马文
dependencies {
//...
annotationProcessor "com.querydsl:querydsl-apt:$querydslVersion:jpa",
'org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.2.Final',
'javax.annotation:javax.annotation-api:1.3.2'
}
compileJava {
options.annotationProcessorPath = configurations.annotationProcessor
}
webmvc-http示例使用 Querydsl 进行。artifactRepositories
4.1.2. 自定义
QuerydslDataFetcher
支持自定义如何将 GraphQL 参数绑定到属性上 以创建查询。默认情况下,参数绑定为“等于” 每个可用属性。要自定义它,您可以使用构建器 提供的方法 a.Predicate
QuerydslDataFetcher
QuerydslBinderCustomizer
存储库本身可能是 的实例。这是自动检测的 并在自动注册期间透明应用。但是,当手动时 构建 Ayou 需要使用构建器方法来应用它。QuerydslBinderCustomizer
QuerydslDataFetcher
QuerydslDataFetcher
支持接口和 DTO 投影以转换查询结果 在返回这些内容以进行进一步的 GraphQL 处理之前。
要了解什么是预测,请参阅Spring Data文档。 要了解如何在 GraphQL 中使用投影,请参阅选择集与投影。 |
要将 Spring 数据投影与 Querydsl 存储库一起使用,请创建投影接口 或目标DTO类,并通过该方法对其进行配置,以获得生成目标类型:projectAs
DataFetcher
class Account {
String name, identifier, description;
Person owner;
}
interface AccountProjection {
String getName();
String getIdentifier();
}
// For single result queries
DataFetcher<AccountProjection> dataFetcher =
QuerydslDataFetcher.builder(repository).projectAs(AccountProjection.class).single();
// For multi-result queries
DataFetcher<Iterable<AccountProjection>> dataFetcher =
QuerydslDataFetcher.builder(repository).projectAs(AccountProjection.class).many();
4.1.3. 自动注册
如果存储库带有注释,则会自动注册 对于尚未注册且返回类型尚未注册的查询 与存储库域类型的匹配。这包括单值和多值 查询。@GraphQlRepository
DataFetcher
默认情况下,查询返回的 GraphQL 类型的名称必须与简单名称匹配 存储库域类型。如果需要,可以使用属性来指定目标 GraphQL 类型名称。typeName
@GraphQlRepository
自动注册检测给定存储库是否实现和 通过构建器方法透明地应用该方法。QuerydslBinderCustomizer
QuerydslDataFetcher
自动注册是通过内置的 从获得。自动启动启动器 检测 bean 并使用它们来初始化。RuntimeWiringConfigurer
QuerydslDataFetcher
@GraphQlRepository
RuntimeWiringConfigurer
自动注册不支持自定义。 如果你需要它,你需要使用构建和 通过运行时布线配置器手动注册。QueryByExampleDataFetcher
DataFetcher
4.2. 示例查询
Spring 数据支持使用示例查询来获取数据。按示例查询 (QBE) 是一种简单的查询技术,不需要 通过特定于存储的查询语言编写查询。
首先声明一个存储库,该存储库是:QueryByExampleExecutor
public interface AccountRepository extends Repository<Account, Long>,
QueryByExampleExecutor<Account> {
}
用于将存储库转换为:QueryByExampleDataFetcher
DataFetcher
// For single result queries
DataFetcher<Account> dataFetcher =
QueryByExampleDataFetcher.builder(repository).single();
// For multi-result queries
DataFetcher<Iterable<Account>> dataFetcher =
QueryByExampleDataFetcher.builder(repository).many();
您现在可以通过运行时布线配置器注册上述内容。DataFetcher
使用 GraphQL 参数映射来创建 存储库并将其用作获取数据的示例对象。Spring Data 支持 JPA、MongoDB、Neo4j 和 Redis。DataFetcher
QueryByExampleDataFetcher
如果存储库是,则构建器返回 sor。Spring Data支持这一点 MongoDB,Neo4j,Redis和R2dbc的变体。ReactiveQueryByExampleExecutor
DataFetcher<Mono<Account>>
DataFetcher<Flux<Account>>
4.2.1. 构建设置
按示例查询已包含在数据存储的 Spring 数据模块中,其中 它受支持,因此无需额外设置即可启用它。
4.2.2. 自定义
QueryByExampleDataFetcher
支持接口和DTO投影来转换查询 结果,然后再返回这些结果以进行进一步的 GraphQL 处理。
要了解什么是预测,请参阅Spring 数据文档。 要了解投影在 GraphQL 中的作用,请参阅选择集与投影。 |
要将 Spring 数据投影与按示例查询存储库一起使用,请创建投影接口 或目标DTO类,并通过该方法对其进行配置,以获得生成目标类型:projectAs
DataFetcher
class Account {
String name, identifier, description;
Person owner;
}
interface AccountProjection {
String getName();
String getIdentifier();
}
// For single result queries
DataFetcher<AccountProjection> dataFetcher =
QueryByExampleDataFetcher.builder(repository).projectAs(AccountProjection.class).single();
// For multi-result queries
DataFetcher<Iterable<AccountProjection>> dataFetcher =
QueryByExampleDataFetcher.builder(repository).projectAs(AccountProjection.class).many();
4.2.3. 自动注册
如果存储库带有注释,则会自动注册 对于尚未注册且返回类型尚未注册的查询 与存储库域类型的匹配。这包括单值和多值 查询。@GraphQlRepository
DataFetcher
默认情况下,查询返回的 GraphQL 类型的名称必须与简单名称匹配 存储库域类型。如果需要,可以使用属性来指定目标 GraphQL 类型名称。typeName
@GraphQlRepository
自动注册是通过内置的 从获得。自动启动启动器 检测 bean 并使用它们来初始化。RuntimeWiringConfigurer
QueryByExampleDataFetcher
@GraphQlRepository
RuntimeWiringConfigurer
自动注册不支持自定义。 如果你需要它,你需要使用构建和 通过运行时布线配置器手动注册。QueryByExampleDataFetcher
DataFetcher
4.3. 选择集与投影
出现的一个常见问题是,GraphQL 选择集与Spring 数据投影相比如何,每个选择集扮演什么角色?
简短的回答是,Spring for GraphQL 不是一个翻译 GraphQL 的数据网关。 直接查询到 SQL 或 JSON 查询中。相反,它可以让您利用现有的Spring。 技术,并且不假设 GraphQL 模式和 基础数据模型。这就是客户端驱动的选择和服务器端转换的原因 的数据模型可以起到互补的作用。
为了更好地理解,请考虑Spring Data将域驱动(DDD)设计推广为: 管理数据层复杂性的推荐方法。在 DDD 中,重要的是 遵守聚合的约束。根据定义,聚合仅在以下情况下有效 完全加载,因为部分加载的聚合可能会对 聚合功能。
在 Spring 数据中,您可以选择是希望按原样公开聚合,还是 是否在将数据模型作为 GraphQL 返回之前对数据模型应用转换 结果。有时做前者就足够了,默认情况下,Querydsl和按示例查询集成会转动GraphQL 选择集到属性路径提示,底层 Spring 数据模块用于 限制选择。
在其他情况下,减少甚至转换基础数据模型很有用 以适应 GraphQL 模式。Spring Data通过接口支持这一点 和 DTO 预测。
接口投影定义一组固定的属性,以公开属性可能或 可能不是,具体取决于数据存储查询结果。有两种 接口投影两者都确定要从底层加载哪些属性 数据来源:null
- 如果无法部分具体化聚合对象,但仍然 想要公开属性的子集。
- 开放接口投影利用 Spring 的 sannotation 和SpEL表达式来应用轻量级 数据转换,例如串联、计算或应用静态函数 到属性。
@Value
DTO投影提供更高级别的自定义,因为您可以放置转换 在构造函数或 getter 方法中编写代码。
DTO 投影从各个属性所在的查询中具体化 由投影本身决定。DTO投影通常与全参数一起使用 构造函数(例如 Java 记录),因此它们只能在所有情况下构造 必填字段(或列)是数据库查询结果的一部分。