5. 数据集成
Spring for GraphQL 允许您利用现有的 Spring 技术,遵循常见的编程模型,通过 GraphQL 公开底层数据源。
本节讨论 Spring Data 的集成层,它提供了一种简单的方法将 Querydsl 或 Query by Example 存储库调整为DataFetcher
,包括用于自动检测和 GraphQL 查询注册标记为存储库的选项 跟@GraphQlRepository
.
5.1. 查询
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();
您现在可以注册上述内容DataFetcher
通过RuntimeWiringConfigurer
.
这DataFetcher
构建一个 QuerydslPredicate
来自 GraphQL 请求参数,并且使用它来获取数据。Spring Data 支持QuerydslPredicateExecutor
对于 JPA,MongoDB 和 LDAP。
如果存储库是ReactiveQuerydslPredicateExecutor
,则构建器返回DataFetcher<Mono<Account>>
或DataFetcher<Flux<Account>>
. Spring Data 支持此MongoDB 的变体。
5.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
}
<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 示例使用 QuerydslartifactRepositories
.
5.1.2. 自定义
QuerydslDataFetcher
支持自定义如何将 GraphQL 参数绑定到属性上创建 QuerydslPredicate
. 默认情况下,参数绑定为“等于”每个可用属性。要自定义它,您可以使用QuerydslDataFetcher
架构工人 提供QuerydslBinderCustomizer
.
存储库本身可以是QuerydslBinderCustomizer
. 这是自动检测的并在自动注册期间透明地应用的。但是,当手动构建一个QuerydslDataFetcher
您将需要使用构建器方法来应用它。
QuerydslDataFetcher
支持接口和 DTO 投影来转换查询结果在返回这些以进行进一步的 GraphQL 处理之前。
要了解什么是投影,请参阅 Spring Data 文档。要了解如何在 GraphQL 中使用投影,请参阅 选择集与投影。 |
要将 Spring Data 投影与 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();
5.1.3. 自动注册
如果存储库的注释为@GraphQlRepository
,它会自动注册对于尚未注册的查询DataFetcher
并且其返回类型与存储库域类型的返回类型匹配。这包括单值和多值 查询。
默认情况下,查询返回的 GraphQL 类型的名称必须与存储库域类型的简单名称匹配。如果需要,您可以使用typeName
属性@GraphQlRepository
以指定目标 GraphQL 类型名称。
自动注册检测给定存储库是否实现QuerydslBinderCustomizer
和 透明地通过QuerydslDataFetcher
builder 方法。
自动注册是通过内置的RuntimeWiringConfigurer
可以从QuerydslDataFetcher
. 自动启动Starters 检测@GraphQlRepository
bean 并使用它们来初始化RuntimeWiringConfigurer
跟。
自动注册不支持自定义。如果需要,则需要使用QueryByExampleDataFetcher
构建和注册DataFetcher
通过RuntimeWiringConfigurer
.
5.2. 示例查询
Spring Data 支持使用 Query by Example 来获取数据。示例查询 (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
通过RuntimeWiringConfigurer
.
这DataFetcher
使用 GraphQL 参数映射创建
存储库,并将其用作获取数据的示例对象。Spring Data 支持QueryByExampleDataFetcher
适用于 JPA、MongoDB、Neo4j 和 Redis。
如果存储库是ReactiveQueryByExampleExecutor
,则构建器返回DataFetcher<Mono<Account>>
或DataFetcher<Flux<Account>>
.Spring Data 支持这一点
MongoDB、Neo4j、Redis 和 R2dbc 的变体。
5.2.2. 自定义
QueryByExampleDataFetcher
支持接口和DTO投影转换查询
结果,然后返回这些结果以进行进一步的 GraphQL 处理。
要了解什么是投影,请参阅 Spring Data 文档。 要了解投影在 GraphQL 中的作用,请参阅选择集与投影。 |
要将 Spring Data 投影与 Query by Example 存储库一起使用,请创建一个投影接口
或目标 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();
5.2.3. 自动注册
如果存储库的注释为@GraphQlRepository
,它会自动注册对于尚未注册的查询DataFetcher
并且其返回类型与存储库域类型的返回类型匹配。这包括单值和多值 查询。
默认情况下,查询返回的 GraphQL 类型的名称必须与存储库域类型的简单名称匹配。如果需要,您可以使用typeName
属性@GraphQlRepository
以指定目标 GraphQL 类型名称。
自动注册是通过内置的RuntimeWiringConfigurer
可以从QueryByExampleDataFetcher
. 自动启动Starters 检测@GraphQlRepository
bean 并使用它们来初始化RuntimeWiringConfigurer
跟。
自动注册不支持自定义。如果需要,则需要使用QueryByExampleDataFetcher
构建和注册DataFetcher
通过RuntimeWiringConfigurer
.
5.3. 选择集与投影
出现的一个常见问题是,GraphQL 选择集与 Spring Data 投影相比如何,每个选择集扮演什么角色?
简短的回答是,Spring for GraphQL 不是将 GraphQL 转换为 GraphQL 的数据网关查询直接转换为 SQL 或 JSON 查询。相反,它允许您利用现有的 Spring技术,并且不假设 GraphQL 模式和底层数据模型。这就是为什么客户端驱动的选择和服务器端转换的数据模型可以发挥互补作用。
为了更好地理解,请考虑 Spring Data 将领域驱动 (DDD) 设计推广为 管理数据层复杂性的建议方法。在 DDD 中,重要的是 以遵守聚合的约束。根据定义,聚合仅在以下情况下有效 全部加载,因为部分加载的聚合可能会对 聚合功能。
在 Spring Data 中,您可以选择是否希望聚合按原样公开,或者 在将数据模型作为 GraphQL 返回之前,是否将转换应用于数据模型 结果。有时做前者就足够了,默认情况下,Querydsl 和 Query by Example 集成会将 GraphQL 选择集到属性路径提示中,底层 Spring Data 模块用于 限制选择。
在其他情况下,减少甚至转换 以适应 GraphQL 架构。Spring Data 通过接口支持这一点 和 DTO 预测。
界面投影定义一组固定的属性,以公开属性可能或
可能不是null
,具体取决于数据存储查询结果。有两种
接口投影,两者都决定了要从底层加载的属性
数据来源:
DTO 投影提供更高级别的自定义,因为您可以放置转换 构造函数或 getter 方法中的代码。
DTO 投影从查询中实现,其中各个属性是 由投影本身决定。DTO 投影通常与全参数一起使用 构造函数(例如 Java 记录),因此只有在所有 必填字段(或列)是数据库查询结果的一部分。