对于最新的稳定版本,请使用 Spring GraphQL 1.3.2spring-doc.cn

对于最新的稳定版本,请使用 Spring GraphQL 1.3.2spring-doc.cn

Spring for GraphQL 允许您利用现有的 Spring 技术,遵循常见的 编程模型以通过 GraphQL 公开底层数据源。spring-doc.cn

本节讨论 Spring Data 的集成层,该集成层提供了一种简单的方法: 将 Querydsl 或 Query by Example 存储库调整为 ,包括 用于自动检测和 GraphQL 查询注册的选项,用于标记的存储库 跟。DataFetcher@GraphQlRepositoryspring-doc.cn

查询 dsl

Spring for GraphQL 支持使用 Querydsl 通过 Spring Data Querydsl 扩展。 Querydsl 提供了一种灵活但类型安全的方法来表示查询谓词 使用 Annotation Processors 生成元模型。spring-doc.cn

例如,将存储库声明为 :QuerydslPredicateExecutorspring-doc.cn

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

然后使用它来创建一个 :DataFetcherspring-doc.cn

// 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-doc.cn

它从 GraphQL 参数构建一个 Querydsl,并使用它来 获取数据。Spring Data 支持 JPA、MongoDB、Neo4j 和 LDAP。DataFetcherPredicateQuerydslPredicateExecutorspring-doc.cn

对于作为 GraphQL 输入类型的单个参数,嵌套一个 level down 并使用参数 sub-map 中的值。QuerydslDataFetcher

如果存储库为 ,则生成器将返回 或 。Spring Data 支持此功能 变体。ReactiveQuerydslPredicateExecutorDataFetcher<Mono<Account>>DataFetcher<Flux<Account>>spring-doc.cn

构建设置

要在构建中配置 Querydsl,请遵循官方参考文档spring-doc.cn

例如:spring-doc.cn

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-doc.cn

定制

QuerydslDataFetcher支持自定义 GraphQL 参数绑定到属性的方式 创建 Querydsl 。默认情况下,参数被绑定为 “is equal to” 每个 available 属性。要自定义它,您可以使用 builder 方法提供 .PredicateQuerydslDataFetcherQuerydslBinderCustomizerspring-doc.cn

存储库本身可以是 的实例。这是自动检测的 并在自动注册期间透明地应用。但是,当手动 构建 您需要使用 Builder 方法来应用它。QuerydslBinderCustomizerQuerydslDataFetcherspring-doc.cn

QuerydslDataFetcher支持接口和 DTO 投影以转换查询结果 在返回这些内容以进行进一步的 GraphQL 处理之前。spring-doc.cn

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

要将 Spring Data 投影与 Querydsl 存储库一起使用,请创建一个投影接口 或目标 DTO 类,并通过该方法对其进行配置,以获取生成目标类型:projectAsDataFetcherspring-doc.cn

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

自动注册

如果存储库带有 注释,则它会自动注册 对于尚未注册且返回类型 与存储库域类型的匹配。这包括单值查询、多值 queries 和分页查询。@GraphQlRepositoryDataFetcherspring-doc.cn

默认情况下,查询返回的 GraphQL 类型的名称必须与简单名称匹配 的存储库域类型。如果需要,您可以使用 的属性 of 指定目标 GraphQL 类型名称。typeName@GraphQlRepositoryspring-doc.cn

对于分页查询,仓库域类型的简单名称必须与不带结尾的类型名称匹配(例如 matches 的 )。对于自动注册,分页是基于偏移的,有 20 个项目 每页。ConnectionConnectionBookBooksConnectionspring-doc.cn

自动注册检测给定存储库是否实现 透明地通过 Builder 方法应用它。QuerydslBinderCustomizerQuerydslDataFetcherspring-doc.cn

自动注册是通过内置的 从 获得。Boot Starter 自动 检测 bean 并使用它们来初始化 with.RuntimeWiringConfigurerQuerydslDataFetcher@GraphQlRepositoryRuntimeWiringConfigurerspring-doc.cn

如果您的存储库 实现或分别。customize(Builder)QuerydslBuilderCustomizerReactiveQuerydslBuilderCustomizerspring-doc.cn

对于作为 GraphQL 输入类型的单个参数,嵌套一个 level down 并使用参数 sub-map 中的值。QuerydslDataFetcher
要了解什么是投影,请参阅 Spring Data 文档。 要了解如何在 GraphQL 中使用投影,请参阅选择集与投影

按示例查询

Spring Data 支持使用 Query by Example 来获取数据。Example 查询 (QBE) 是一种简单的查询技术,不需要 you 通过特定于 store 的查询语言编写查询。spring-doc.cn

首先声明一个存储库,该存储库为:QueryByExampleExecutorspring-doc.cn

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

用于将存储库转换为 :QueryByExampleDataFetcherDataFetcherspring-doc.cn

// 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-doc.cn

使用 GraphQL 参数映射来创建 repository 并使用它作为示例对象来获取数据。Spring Data 支持 JPA、MongoDB、Neo4j 和 Redis。DataFetcherQueryByExampleDataFetcherspring-doc.cn

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

如果存储库为 ,则生成器将返回 或 。Spring Data 支持此功能 MongoDB、Neo4j、Redis 和 R2dbc 的变体。ReactiveQueryByExampleExecutorDataFetcher<Mono<Account>>DataFetcher<Flux<Account>>spring-doc.cn

构建设置

Query by Example 已包含在数据存储的 Spring Data 模块中,其中 它受支持,因此无需额外设置即可启用它。spring-doc.cn

定制

QueryByExampleDataFetcher支持接口和 DTO 投影以转换查询 结果,然后再返回这些内容以供进一步的 GraphQL 处理。spring-doc.cn

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

要将 Spring Data 投影与 Query by Example 存储库一起使用,请创建一个投影接口 或目标 DTO 类,并通过该方法对其进行配置,以获取生成目标类型:projectAsDataFetcherspring-doc.cn

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

自动注册

如果存储库带有 注释,则它会自动注册 对于尚未注册且返回类型 与存储库域类型的匹配。这包括单值查询、多值 queries 和分页查询。@GraphQlRepositoryDataFetcherspring-doc.cn

默认情况下,查询返回的 GraphQL 类型的名称必须与简单名称匹配 的存储库域类型。如果需要,您可以使用 的属性 of 指定目标 GraphQL 类型名称。typeName@GraphQlRepositoryspring-doc.cn

对于分页查询,仓库域类型的简单名称必须与不带结尾的类型名称匹配(例如 matches 的 )。对于自动注册,分页是基于偏移的,有 20 个项目 每页。ConnectionConnectionBookBooksConnectionspring-doc.cn

自动注册是通过内置的 从 获得。Boot Starter 自动 检测 bean 并使用它们来初始化 with.RuntimeWiringConfigurerQueryByExampleDataFetcher@GraphQlRepositoryRuntimeWiringConfigurerspring-doc.cn

如果您的存储库 实现或分别。customize(Builder)QueryByExampleBuilderCustomizerReactiveQueryByExampleBuilderCustomizerspring-doc.cn

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

选择集与投影

出现的一个常见问题是,GraphQL 选择集与 Spring Data 预测相比如何,每个选择集扮演什么角色?spring-doc.cn

简短的回答是,Spring for GraphQL 不是转换 GraphQL 的数据网关 查询直接转换为 SQL 或 JSON 查询。相反,它允许您利用现有的 Spring 技术,并且不假定 GraphQL 架构与 底层数据模型。这就是客户驱动的选择和服务器端转换的原因 的数据模型可以起到互补的作用。spring-doc.cn

为了更好地理解,请考虑 Spring Data 将域驱动 (DDD) 设计提升为 管理数据层复杂性的推荐方法。在 DDD 中,它很重要 以遵守聚合的约束。根据定义,聚合仅在以下情况下有效 load 的 聚合功能。spring-doc.cn

在 Spring Data 中,您可以选择是希望聚合按原样公开,还是 是否在将数据模型作为 GraphQL 返回之前将其应用于数据模型 结果。有时,执行前者就足够了,默认情况下,QuerydslQuery by Example 集成会使 GraphQL selection set 的 set 设置为 property path 提示,底层 Spring Data 模块使用 限制选择。spring-doc.cn

在其他情况下,减少甚至转换 来适应 GraphQL 架构。Spring Data 通过 Interface 支持此功能 和 DTO Projections。spring-doc.cn

接口投影定义一组固定的属性,以公开属性可能或 可能不是 ,具体取决于 Data Store 查询结果。有两种 接口投影,这两者都决定了要从底层加载哪些属性 数据来源:nullspring-doc.cn

DTO 投影提供了更高级别的自定义,因为您可以放置转换 代码 (code 要么在 constructor 要么 getter methods) 中。spring-doc.cn

DTO 投影从各个属性所在的查询中实现 由投影本身确定。DTO 投影通常与 full-args 一起使用 构造函数(例如 Java 记录),因此只有在所有 必填字段(或列)是数据库查询结果的一部分。spring-doc.cn

滚动

分页中所述,GraphQL 游标连接规范定义了一个 使用 、 和 schema 类型进行分页的机制,而 GraphQL Java 提供等效的 Java 类型表示形式。ConnectionEdgePageInfospring-doc.cn

Spring for GraphQL 提供了内置实现来适应 Spring Data 分页类型和透明。您可以配置 如下:ConnectionAdapterWindowSlicespring-doc.cn

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 注册 visitor 类型。

在请求端,控制器方法可以声明 ScrollSubrange 方法参数以向前分页 或向后。为此,您必须将 CursorStrategy 支持声明为 bean。ScrollPositionspring-doc.cn

Boot Starter 声明一个 bean,如果 Spring Data 在 Classpath 上,则如上所述注册 。CursorStrategy<ScrollPosition>ConnectionFieldTypeVisitorspring-doc.cn

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

关键帧集位置

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

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

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

然后,您可以创建 :JsonKeysetCursorStrategyspring-doc.cn

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-doc.cn

排序

Spring for GraphQL 定义了一个从 GraphQL 参数创建的。 使用抽象方法实现 Contract 以提取排序 direction 和 properties 的 Direction 和 Properties 进行访问。要启用对作为控制器方法参数的支持, 您需要声明一个 bean。SortStrategySortAbstractSortStrategySortSortStrategyspring-doc.cn