Spring for GraphQL 允许您利用现有的 Spring 技术,遵循常见的 对模型进行编程,以通过 GraphQL 公开基础数据源。Spring中文文档

本节讨论 Spring Data 的集成层,该集成层提供了一种简单的方法 将 Querydsl 或 Query by Example 存储库改编为 ,包括 用于自动检测和 GraphQL 查询注册标记的存储库的选项 跟。DataFetcher@GraphQlRepositorySpring中文文档

查询

Spring for GraphQL 支持使用 Querydsl 通过 Spring Data Querydsl 扩展。 Querydsl 提供了一种灵活且类型安全的方法,可以通过以下方式表达查询谓词 使用注释处理器生成元模型。Spring中文文档

例如,将存储库声明为:QuerydslPredicateExecutorSpring中文文档

public interface AccountRepository extends Repository<Account, Long>,
			QuerydslPredicateExecutor<Account> {
}

然后用它来创建一个:DataFetcherSpring中文文档

// For single result queries
DataFetcher<Account> dataFetcher =
		QuerydslDataFetcher.builder(repository).single();

// For multi-result queries
DataFetcher<Iterable<Account>> dataFetcher =
		QuerydslDataFetcher.builder(repository).many();

// For paginated queries
DataFetcher<Iterable<Account>> dataFetcher =
		QuerydslDataFetcher.builder(repository).scrollable();

现在,您可以通过 RuntimeWiringConfigurer 注册上述内容。DataFetcherSpring中文文档

从 GraphQL 参数构建 Querydsl,并使用它来 获取数据。Spring Data 支持 JPA、MongoDB、Neo4j 和 LDAP。DataFetcherPredicateQuerydslPredicateExecutorSpring中文文档

对于作为 GraphQL 输入类型的单个参数,嵌套一个 降低水平,并使用参数子映射中的值。QuerydslDataFetcher

如果存储库为 ,则构建器返回 或 。Spring Data 支持这一点 MongoDB 和 Neo4j 的变体。ReactiveQuerydslPredicateExecutorDataFetcher<Mono<Account>>DataFetcher<Flux<Account>>Spring中文文档

构建设置

若要在构建中配置 Querydsl,请遵循官方参考文档Spring中文文档

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
}
<dependencies>
	<!-- ... -->
	<dependency>
		<groupId>com.querydsl</groupId>
		<artifactId>querydsl-apt</artifactId>
		<version>${querydsl.version}</version>
		<classifier>jpa</classifier>
		<scope>provided</scope>
	</dependency>
	<dependency>
		<groupId>org.hibernate.javax.persistence</groupId>
		<artifactId>hibernate-jpa-2.1-api</artifactId>
		<version>1.0.2.Final</version>
	</dependency>
	<dependency>
		<groupId>javax.annotation</groupId>
		<artifactId>javax.annotation-api</artifactId>
		<version>1.3.2</version>
	</dependency>
</dependencies>
<plugins>
	<!-- Annotation processor configuration -->
	<plugin>
		<groupId>com.mysema.maven</groupId>
		<artifactId>apt-maven-plugin</artifactId>
		<version>${apt-maven-plugin.version}</version>
		<executions>
			<execution>
				<goals>
					<goal>process</goal>
				</goals>
				<configuration>
					<outputDirectory>target/generated-sources/java</outputDirectory>
					<processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
				</configuration>
			</execution>
		</executions>
	</plugin>
</plugins>

webmvc-http 示例将 Querydsl 用于 。artifactRepositoriesSpring中文文档

定制

QuerydslDataFetcher支持自定义 GraphQL 参数绑定到属性的方式 创建 Querydsl 。默认情况下,参数绑定为“等于” 每个可用属性。要自定义它,您可以使用构建器 提供 .PredicateQuerydslDataFetcherQuerydslBinderCustomizerSpring中文文档

存储库本身可以是 的实例。这是自动检测的 并在自动注册期间透明地应用。但是,当手动 构建 您需要使用构建器方法来应用它。QuerydslBinderCustomizerQuerydslDataFetcherSpring中文文档

QuerydslDataFetcher支持接口和 DTO 投影来转换查询结果 在返回这些以进行进一步的 GraphQL 处理之前。Spring中文文档

要了解什么是预测,请参阅 Spring Data 文档。 要了解如何在 GraphQL 中使用投影,请参阅选择集与投影

要将 Spring Data 投影与 Querydsl 存储库一起使用,请创建投影接口 或目标 DTO 类,并通过该方法对其进行配置,以获得生成目标类型:projectAsDataFetcherSpring中文文档

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();

自动注册

如果存储库使用 注释,则会自动注册 对于尚未注册且返回类型尚未注册的查询 与存储库域类型匹配。这包括单值查询、多值查询 查询和分页查询。@GraphQlRepositoryDataFetcherSpring中文文档

默认情况下,查询返回的 GraphQL 类型的名称必须与简单名称匹配 存储库域类型。如果需要,可以使用 的属性来指定目标 GraphQL 类型名称。typeName@GraphQlRepositorySpring中文文档

对于分页查询,存储库域类型的简单名称必须与类型名称匹配,而不带结尾(例如 匹配)。对于自动注册,分页是基于偏移量的,有 20 个项目 每页。ConnectionConnectionBookBooksConnectionSpring中文文档

自动注册检测给定存储库是否实现和 通过构建器方法透明地应用它。QuerydslBinderCustomizerQuerydslDataFetcherSpring中文文档

自动注册是通过内置的 从 获得。Boot Starter 自动 检测 Bean 并使用它们来初始化 with。RuntimeWiringConfigurerQuerydslDataFetcher@GraphQlRepositoryRuntimeWiringConfigurerSpring中文文档

自动注册通过调用存储库实例来应用自定义项,如果您的存储库 分别实现或。customize(Builder)QuerydslBuilderCustomizerReactiveQuerydslBuilderCustomizerSpring中文文档

对于作为 GraphQL 输入类型的单个参数,嵌套一个 降低水平,并使用参数子映射中的值。QuerydslDataFetcher
要了解什么是预测,请参阅 Spring Data 文档。 要了解如何在 GraphQL 中使用投影,请参阅选择集与投影

按示例查询

Spring Data 支持使用 Query by Example 来获取数据。示例查询 (QBE) 是一种简单的查询技术,不需要 通过特定于存储的查询语言编写查询。Spring中文文档

首先声明一个存储库,该存储库是:QueryByExampleExecutorSpring中文文档

public interface AccountRepository extends Repository<Account, Long>,
			QueryByExampleExecutor<Account> {
}

用于将存储库转换为:QueryByExampleDataFetcherDataFetcherSpring中文文档

// For single result queries
DataFetcher<Account> dataFetcher =
		QueryByExampleDataFetcher.builder(repository).single();

// For multi-result queries
DataFetcher<Iterable<Account>> dataFetcher =
		QueryByExampleDataFetcher.builder(repository).many();

// For paginated queries
DataFetcher<Iterable<Account>> dataFetcher =
		QueryByExampleDataFetcher.builder(repository).scrollable();

现在,您可以通过 RuntimeWiringConfigurer 注册上述内容。DataFetcherSpring中文文档

使用 GraphQL 参数映射创建域类型 存储库,并将其用作获取数据的示例对象。Spring Data 支持 JPA、MongoDB、Neo4j 和 Redis。DataFetcherQueryByExampleDataFetcherSpring中文文档

对于作为 GraphQL 输入类型的单个参数,向下嵌套一级,并与参数子映射中的值绑定。QueryByExampleDataFetcher

如果存储库为 ,则构建器返回 或 。Spring Data 支持这一点 MongoDB、Neo4j、Redis 和 R2dbc 的变体。ReactiveQueryByExampleExecutorDataFetcher<Mono<Account>>DataFetcher<Flux<Account>>Spring中文文档

构建设置

按示例查询已包含在数据存储的 Spring Data 模块中,其中 它受支持,因此无需额外设置即可启用它。Spring中文文档

定制

QueryByExampleDataFetcher支持接口和 DTO 投影来转换查询 结果,然后返回这些结果以进行进一步的 GraphQL 处理。Spring中文文档

要了解什么是投影,请参阅 Spring Data 文档。 要了解投影在 GraphQL 中的作用,请参阅选择集与投影

要将 Spring Data 投影与 Query by Example 存储库一起使用,请创建投影接口 或目标 DTO 类,并通过该方法对其进行配置,以获得生成目标类型:projectAsDataFetcherSpring中文文档

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();

自动注册

如果存储库使用 注释,则会自动注册 对于尚未注册且返回类型尚未注册的查询 与存储库域类型匹配。这包括单值查询、多值查询 查询和分页查询。@GraphQlRepositoryDataFetcherSpring中文文档

默认情况下,查询返回的 GraphQL 类型的名称必须与简单名称匹配 存储库域类型。如果需要,可以使用 的属性来指定目标 GraphQL 类型名称。typeName@GraphQlRepositorySpring中文文档

对于分页查询,存储库域类型的简单名称必须与类型名称匹配,而不带结尾(例如 匹配)。对于自动注册,分页是基于偏移量的,有 20 个项目 每页。ConnectionConnectionBookBooksConnectionSpring中文文档

自动注册是通过内置的 从 获得。Boot Starter 自动 检测 Bean 并使用它们来初始化 with。RuntimeWiringConfigurerQueryByExampleDataFetcher@GraphQlRepositoryRuntimeWiringConfigurerSpring中文文档

自动注册通过调用存储库实例来应用自定义项,如果您的存储库 分别实现或。customize(Builder)QueryByExampleBuilderCustomizerReactiveQueryByExampleBuilderCustomizerSpring中文文档

对于作为 GraphQL 输入类型的单个参数,向下嵌套一级,并与参数子映射中的值绑定。QueryByExampleDataFetcher
要了解什么是投影,请参阅 Spring Data 文档。 要了解投影在 GraphQL 中的作用,请参阅选择集与投影

选择集与投影

出现的一个常见问题是,GraphQL 选择集与 Spring Data 投影相比如何,每个预测集扮演什么角色?Spring中文文档

简短的回答是,Spring for GraphQL 不是翻译 GraphQL 的数据网关 直接查询到 SQL 或 JSON 查询中。相反,它允许您利用现有的 Spring 技术,并且不假设 GraphQL 模式和 基础数据模型。这就是客户端驱动的选择和服务器端转换的原因 的数据模型可以起到互补的作用。Spring中文文档

为了更好地理解,请考虑 Spring Data 将领域驱动 (DDD) 设计提升为 管理数据层复杂性的推荐方法。在 DDD 中,这很重要 遵守聚合的约束。根据定义,聚合仅在以下情况下才有效 整体加载,因为部分加载的聚合可能会对 聚合功能。Spring中文文档

在 Spring Data 中,您可以选择是否希望聚合按原样公开,或者 是否在将数据模型作为 GraphQL 返回之前将其应用于数据模型 结果。有时,执行前者就足够了,默认情况下,QuerydslQuery by Example 集成会将 GraphQL 转换为 GraphQL 选择设置到属性路径中提示底层 Spring Data 模块用于 限制选择。Spring中文文档

在其他情况下,减少甚至转换基础数据模型很有用 order 以适应 GraphQL 模式。Spring Data通过接口支持这一点 和 DTO 预测。Spring中文文档

接口投影定义一组固定的属性,以公开属性可能或 可能不是 ,具体取决于数据存储查询结果。有两种 接口投影都决定了要从基础加载哪些属性 数据来源:nullSpring中文文档

DTO 投影提供更高级别的自定义,因为您可以放置转换 在构造函数或 getter 方法中编写代码。Spring中文文档

DTO 投影从各个属性所在的查询中实现 由投影本身决定。DTO 投影通常与全参数一起使用 构造函数(例如 Java 记录),因此它们只能在以下情况下构造 必填字段(或列)是数据库查询结果的一部分。Spring中文文档

滚动

分页中所述,GraphQL 游标连接规范定义了一个 使用 、 和 模式类型进行分页的机制,而 GraphQL Java 提供等效的 Java 类型表示。ConnectionEdgePageInfoSpring中文文档

Spring for GraphQL 提供了内置的实现来适应 Spring Data 分页类型和透明。您可以对其进行配置 如下:ConnectionAdapterWindowSliceSpring中文文档

CursorStrategy<ScrollPosition> strategy = CursorStrategy.withEncoder(
		new ScrollPositionCursorStrategy(),
		CursorEncoder.base64()); (1)

GraphQLTypeVisitor visitor = ConnectionFieldTypeVisitor.create(List.of(
		new WindowConnectionAdapter(strategy),
		new SliceConnectionAdapter(strategy))); (2)

GraphQlSource.schemaResourceBuilder()
		.schemaResources(..)
		.typeDefinitionConfigurer(..)
		.typeVisitors(List.of(visitor)); (3)
1 创建转换为 Base64 编码游标的策略。ScrollPosition
2 创建类型 visitor 进行适应并从 s 返回。WindowSliceDataFetcher
3 注册类型访客。

在请求端,控制器方法可以声明 ScrollSubrange 方法参数以向前分页 或向后。为此,您必须将 CursorStrategy 支持声明为 Bean。ScrollPositionSpring中文文档

Boot Starter 声明一个 bean,如果 Spring Data 在类路径上,则如上所示注册 bean。CursorStrategy<ScrollPosition>ConnectionFieldTypeVisitorSpring中文文档

1 创建转换为 Base64 编码游标的策略。ScrollPosition
2 创建类型 visitor 进行适应并从 s 返回。WindowSliceDataFetcher
3 注册类型访客。

键集位置

对于 ,需要从键集创建游标,该键集是 本质上是键值对的 a。要决定如何从键集创建游标, 您可以使用 . 默认情况下,将密钥集写入 JSON。这适用于 像 String、Boolean、Integer 和 Double 一样简单,但其他的无法恢复到 没有目标类型信息的相同类型。Jackson 库具有默认的打字功能 可以在 JSON 中包含类型信息。为了安全地使用它,您必须指定一个列表 允许的类型。例如:KeysetScrollPositionMapScrollPositionCursorStrategyCursorStrategy<Map<String, Object>>JsonKeysetCursorStrategyMapSpring中文文档

PolymorphicTypeValidator validator = BasicPolymorphicTypeValidator.builder()
		.allowIfBaseType(Map.class)
		.allowIfSubType(ZonedDateTime.class)
		.build();

ObjectMapper mapper = new ObjectMapper();
mapper.activateDefaultTyping(validator, ObjectMapper.DefaultTyping.NON_FINAL);

然后,您可以创建:JsonKeysetCursorStrategySpring中文文档

ObjectMapper mapper = ... ;

CodecConfigurer configurer = ServerCodecConfigurer.create();
configurer.defaultCodecs().jackson2JsonDecoder(new Jackson2JsonDecoder(mapper));
configurer.defaultCodecs().jackson2JsonEncoder(new Jackson2JsonEncoder(mapper));

JsonKeysetCursorStrategy strategy = new JsonKeysetCursorStrategy(configurer);

默认情况下,如果创建时没有 a 和 Jackson 库位于类路径上,如上所述的自定义项适用于 、 和 中的任何类型。JsonKeysetCursorStrategyCodecConfigurerDateCalendarjava.timeSpring中文文档

排序

Spring for GraphQL 定义了一个要从 GraphQL 参数创建的参数。 使用抽象方法实现合约以提取排序 方向和属性。若要启用对 as a controller 方法参数的支持, 您需要声明一个 Bean。SortStrategySortAbstractSortStrategySortSortStrategySpring中文文档