我在n+1
我的一个应用程序中面临graphql问题,我在java中使用graphql和restful webservice。我正在使用schemagen-graphql
withspring-data-jpa
连接到我的 oracle 数据库。我看到了很多帖子,但大多数答案都是graphql-node.js
实施。任何与java相关的东西都会很好。
问问题
3048 次
1 回答
14
我不太了解schemagen-graphql
它在这里是否重要,但总的来说,目前有 3 个选项graphql-java
:
- 解析父字段时(即在父字段中)预取您需要的内容
DataFetcher
。您可以通过检查DataFetchingFieldSelectionSet
. 如果预取的数据不自然地适合结果对象,您可以将其存储在 中,LocalContext
并在解析子字段值时使用它。这篇博文很好地解释了这种方法。 - 使用已弃用(如果您使用 下的类
graphql.execution
)或实验性(如果使用 下的类)方法来使用和 usinggraphql.execution.nextgen
注释数据获取器。 此选项易于理解和使用,但与您息息相关(旧版本在处理空值时并未完全遵守规范)。 遗憾的是,它的记录很差,但归结为:@Batched
BatchedExecutionStrategy
BatchedExecutionStrategy
- 用注释
DataFetcher#get
方法@Batched
- 在该数据获取器中,
DataFetchingEnvironment#getSource
将始终返回源对象列表(而不是一个)。 - 这样的数据获取器必须始终返回结果列表(与源列表的长度相同)。这允许以简单的方式批量加载对象。一个明显的例子是一次从关系数据库中加载许多行:
- 用注释
List<Article> articles = DataFetchingEnvironment.getSource(); //source is a list List<Long> authorIds = articles.stream.map(article -> article.getAuthodId()).collect(Collectors.toList()); //fetch all the authors in one go SELECT * FROM Author WHERE author_id IN (authorIds)
- 用于
DataLoader
获取您的数据,而不是直接获取它。这个想法与最初的数据加载器 JavaScript 库非常相似。仅适用于默认值AsyncExecutionStrategy
且仅适用于查询(因此不要期望它适用于突变和订阅)。
您可以提供DataLoaderRegistry
in的实例ExecutionInput
,并且您通常希望在每个请求上重新创建数据加载器和注册表(如果它们是无状态的,则可以共享批处理加载器):
DataLoaderRegistry loaders = ...; //initialize your loaders, usually per request
graphQL.execute(ExecutionInput.newExecutionInput()
.query(operation)
.dataLoaderRegistry(loaders) //add the registry to input
.build());
然后在你的DataFetcher
你总是可以通过以下方式获得DataLoader
你需要的DataFetchingEnvironment#getDataLoader(String dataLoaderName)
:
return env.getDataLoader("authors").load(article.getAuthorId());
作为旁注,您可能想查看我自己的库,用于从 Java 生成 GraphQL API,GraphQL-SPQR。这是使用它的最小演示@Batched
。
至于DataLoader,逻辑同上,进入DataLoaderRegistry
via@GraphQLEnvironment
注解:
@GrapgQLQuery
public CompletableFuture<Author> author(@GraphQLContext Article article, @GraphQLEnvironment ResolutionEnvironment env) {
return env.dataFetchingEnvironment.getDataLoader("authors").load(article.getAuthorId())
}
我可能还会添加一个专门的注释,比如@DataLoader("authors")
直接注入加载器。
于 2018-01-07T00:59:00.080 回答