|
对于最新稳定版本,请使用 Spring GraphQL 2.0.0! |
数据集成
Spring for GraphQL 允许您利用现有的 Spring 技术,遵循常见的编程模型,通过 GraphQL 暴露底层数据源。
本节讨论了 Spring Data 的一个集成层,该层提供了一种简单的方式来将 Querydsl 或 Query by Example(示例查询)仓库适配到数据费彻,包括自动检测选项和标记仓库的GraphQL查询注册 跟@GraphQlRepository.
Querydsl
Spring for GraphQL 支持使用 Querydsl 通过Spring Data Querydsl 扩展获取数据。Querydsl 提供了一种灵活但类型安全的表达方法,通过使用注释处理器生成元模型。
例如,声明一个仓库为QuerydslPredicateExecutor:
public interface AccountRepository extends Repository<Account, Long>,
QuerydslPredicateExecutor<Account> {
}
然后用它来创建一个数据费彻:
// 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.
这数据费彻构建一个 Querydsl谓语并利用它来获取数据。Spring Data 支持QuerydslPredicateExecutor适用于JPA、MongoDB、Neo4j和LDAP。
对于单个参数 是 GraphQL 输入类型,QuerydslDataFetcher嵌套一个层级下降,并使用参数子映射中的值。 |
如果仓库是ReactiveQuerydslPredicateExecutor,建造者回归DataFetcher<Mono<Account>>或DataFetcher<Flux<Account>>. Spring Data 支持这种MongoDB 和 Neo4j 的变体。
构建设置
要在你的构建中配置 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文物仓库.
定制
QuerydslDataFetcher支持自定义 GraphQL 参数如何绑定到属性上以创建 Querydsl谓语. 默认情况下,参数被绑定为“等于”每个可用属性。为了自定义,你可以使用QuerydslDataFetcher架构工人 提供QuerydslBinderCustomizer.
一个仓库本身可以是QuerydslBinderCustomizer. 这是自动检测的并在自动注册过程中透明地应用。然而,当手动构建一个QuerydslDataFetcher你需要使用架构方法来应用。
QuerydslDataFetcher支持接口和DTO投影以转换查询结果然后返回这些数据以便进一步处理GraphQL。
| 想了解什么是投影,请参考 Spring Data 文档。想了解如何在 GraphQL 中使用投影,请参见 Selection Set 与 Projections。 |
要在 Querydsl 仓库中使用 Spring Data 投影,可以创建一个投影接口或者创建一个目标 DTO 类,并通过项目As获得数据费彻生成目标类型:
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();
自动注册
如果仓库被注释为@GraphQlRepository,自动注册
对于尚未注册的查询数据费彻以及返回类型
与仓库域类型匹配。这包括单值查询、多值查询
查询,以及分页查询。
默认情况下,查询返回的 GraphQL 类型名称必须与简单名称相匹配
属于仓库域类型。如果需要,你可以使用类型名称属性@GraphQlRepository以指定目标 GraphQL 类型名称。
对于分页查询,仓库域类型的简单名称必须与连接类型名称,但不含连接结尾(例如:书比赛书连接).自动注册时,分页采用20条偏移方式
每页。
自动注册检测给定仓库是否实现了QuerydslBinderCustomizer和
透明地通过QuerydslDataFetcher架构方法。
自动注册通过内置功能实现RuntimeWiringConfigurer这可以是
来源QuerydslDataFetcher.启动Starters自动启动
检测@GraphQlRepository并用它们来初始化RuntimeWiringConfigurer跟。
自动注册通过呼叫应用自定义定制(建造)在仓库实例中,如果你的仓库
实现QuerydslBuilderCustomizer或ReactiveQuerydslBuilderCustomizer分别。
示例查询
Spring Data 支持使用示例查询来获取数据。示例查询(QBE)是一种简单的查询技术,不需要 你可以通过商店特定的查询语言来写查询。
首先声明一个仓库QueryByExampleExecutor:
public interface AccountRepository extends Repository<Account, Long>,
QueryByExampleExecutor<Account> {
}
用QueryByExampleDataFetcher将仓库转变为数据费彻:
// 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.
这数据费彻使用 GraphQL 参数映射来创建
并以此为示例对象来获取数据。Spring Data 支持QueryByExampleDataFetcher适用于JPA、MongoDB、Neo4j和Redis。
对于单个参数 是 GraphQL 输入类型,QueryByExampleDataFetcher嵌套一层,并绑定参数子映射的值。 |
如果仓库是ReactiveQueryByExampleExecutor,建造者回归DataFetcher<Mono<Account>>或DataFetcher<Flux<Account>>.Spring Data 支持这一点
适用于 MongoDB、Neo4j、Redis 和 R2dbc 的变体。
定制
QueryByExampleDataFetcher支持接口和DTO投影以实现查询转换
结果后返回进行进一步的GraphQL处理。
要使用 Spring Data 投影和示例查询仓库,可以创建一个投影接口
或者一个目标DTO类,并通过项目As获得数据费彻生成目标类型:
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();
自动注册
如果仓库被注释为@GraphQlRepository,自动注册
对于尚未注册的查询数据费彻以及返回类型
与仓库域类型匹配。这包括单值查询、多值查询
查询,以及分页查询。
默认情况下,查询返回的 GraphQL 类型名称必须与简单名称相匹配
属于仓库域类型。如果需要,你可以使用类型名称属性@GraphQlRepository以指定目标 GraphQL 类型名称。
对于分页查询,仓库域类型的简单名称必须与连接类型名称,但不含连接结尾(例如:书比赛书连接).自动注册时,分页采用20条偏移方式
每页。
自动注册通过内置功能实现RuntimeWiringConfigurer这可以是
来源QueryByExampleDataFetcher.启动Starters自动启动
检测@GraphQlRepository并用它们来初始化RuntimeWiringConfigurer跟。
自动注册通过呼叫应用自定义定制(建造)在仓库实例中,如果你的仓库
实现QueryByExampleBuilderCustomizer或ReactiveQueryByExampleBuilderCustomizer分别。
选择集与投影
一个常见的问题是,GraphQL 的选择集与 Spring Data 预测相比如何?各自扮演什么角色?
简短的回答是,Spring for GraphQL 并不是一个能转换 GraphQL 的数据网关 直接对SQL或JSON查询进行查询。相反,它让你可以利用现有的春季 技术上并不假设GraphQL模式与 底层数据模型。这就是为什么需要以客户端为驱动的选择和服务器端转型 数据模型可以发挥互补的作用。
为了更好地理解,考虑 Spring Data 推广领域驱动(DDD)设计为 管理数据层复杂性的推荐方法。在DDD中,这很重要 以遵守总量的约束。根据定义,聚合仅当 全部加载,因为部分负载的聚合可能会对 聚合功能。
在Spring Data中,你可以选择是直接暴露聚合,还是 是否在返回为GraphQL之前对数据模型进行转换 结果。有时候只要做前者就够了,默认情况下,Querydsl 和 Query by Example 集成会把 GraphQL 转换起来 选择集进入属性路径暗示底层的Spring数据模块使用 限制选择。
在其他情况下,简化甚至转换底层数据模型是有用的 以适应GraphQL模式。Spring Data 通过接口支持此功能 以及DTO预测。
界面投影定义了一组固定的属性,用于揭示性质可能或
可能不是零,取决于数据存储查询结果。有两种
接口投影,这两者都决定了从底层加载哪些属性
数据来源:
DTO投影提供了更高的自定义层次,因为你可以放置变换 代码可以是在构造函数或 getter 方法中编写。
DTO 投影是从查询中实现的,其中各个属性为 由投影本身决定。DTO 投影通常用于全 args 构造子(例如 Java 记录),因此只有当所有 必填字段(或列)是数据库查询结果的一部分。
滚动
正如分页中所述,GraphQL 光标连接规范定义了
分页机制连接,边缘和页面信息模式类型,而
GraphQL Java 提供等效的 Java 类型表示。
Spring for GraphQL 内置了连接适配器用于适应
Spring Data 分页类型窗和片透明。你可以配置那个
如下:
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编码的光标。 |
| 2 | 创建类型访问者以适应窗和片返回数据费彻s. |
| 3 | 登记访客类型。 |
在请求端,控制器方法可以声明ScrollSubrange方法参数来分页
或者倒着。要让这个功能生效,你必须声明一个光标策略支持卷轴位置像豆子一样。
启动Starters会声明CursorStrategy<ScrollPosition>豆子,并注册了ConnectionFieldTypeVisitor如上所示,如果Spring Data在类路径上。
键盘组位置
为KeysetScrollPosition(关键集滚动位置),光标需要由一个键集创建,即
本质上是地图关键值对的集合。为了决定如何从键集创建光标,
你可以配置滚动位置游标策略跟CursorStrategy<Map<String, Object>>.
默认情况下,JsonKeysetCursorStrategy写入密钥集地图转为JSON。这在
简单的,比如字符串、布尔、整数和双,但其他的则无法恢复到
同一种类型,但没有目标类型信息。Jackson 库有默认的打字功能
可以包含 JSON 中的类型信息。为了安全使用,您必须指定一份以下列表
允许的类型。例如:
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);
默认情况下,如果JsonKeysetCursorStrategy在没有CodecConfigurer以及
Jackson 库在类路径上,应用了上述自定义日期,日历,以及任意类型java.time.
排序
Spring for GraphQL 定义了一个排序策略创造排序从GraphQL参数中获得。摘要排序策略用抽象方法实现该契约以提取排序
方向和属性。以支持以下内容排序作为控制器方法参数,
你需要申报排序策略豆。