此版本仍在开发中,尚未被视为稳定版本。最新的稳定版本请使用 Spring GraphQL 1.3.1

此版本仍在开发中,尚未被视为稳定版本。最新的稳定版本请使用 Spring GraphQL 1.3.1

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

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

查询

Spring for GraphQL 支持使用 Querydsl 通过 Spring Data 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();

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

现在,您可以通过 RuntimeWiringConfigurer 注册上述内容。DataFetcher

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

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

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

构建设置

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

例如:

  • Gradle

  • Maven

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 用于 。artifactRepositories

定制

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

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

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

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

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

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

自动注册

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

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

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

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

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

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

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

按示例查询

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

首先声明一个存储库,该存储库是:QueryByExampleExecutor

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

用于将存储库转换为:QueryByExampleDataFetcherDataFetcher

// 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 注册上述内容。DataFetcher

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

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

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

构建设置

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

定制

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

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

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

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

自动注册

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

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

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

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

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

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

选择集与投影

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

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

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

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

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

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

  • 如果您无法部分具体化聚合对象,但您仍然无法实现,则闭合界面投影会很有帮助 想要公开属性的子集。

  • 开放界面投影利用 Spring 的注释和 SpEL 表达式来应用轻量级 数据转换,例如串联、计算或应用静态函数 到属性。@Value

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

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

滚动

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

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

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。ScrollPosition

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

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

键集位置

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

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

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

然后,您可以创建:JsonKeysetCursorStrategy

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.time

排序

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