4

我在n+1我的一个应用程序中面临graphql问题,我在java中使用graphql和restful webservice。我正在使用schemagen-graphqlwithspring-data-jpa连接到我的 oracle 数据库。我看到了很多帖子,但大多数答案都是graphql-node.js实施。任何与java相关的东西都会很好。

4

1 回答 1

14

我不太了解schemagen-graphql它在这里是否重要,但总的来说,目前有 3 个选项graphql-java

  1. 解析父字段时(即在父字段中)预取您需要的内容DataFetcher。您可以通过检查DataFetchingFieldSelectionSet. 如果预取的数据不自然地适合结果对象,您可以将其存储在 中,LocalContext并在解析子字段值时使用它。这篇博文很好地解释了这种方法。
  2. 使用已弃用(如果您使用 下的类graphql.execution)或实验性(如果使用 下的类)方法来使用和 usinggraphql.execution.nextgen注释数据获取器。 此选项易于理解和使用,但与您息息相关(旧版本在处理空值时并未完全遵守规范)。 遗憾的是,它的记录很差,但归结为: @BatchedBatchedExecutionStrategy
    BatchedExecutionStrategy
    1. 用注释DataFetcher#get方法@Batched
    2. 在该数据获取器中,DataFetchingEnvironment#getSource将始终返回源对象列表(而不是一个)。
    3. 这样的数据获取器必须始终返回结果列表(与源列表的长度相同)。这允许以简单的方式批量加载对象。一个明显的例子是一次从关系数据库中加载许多行:
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)
  1. 用于DataLoader获取您的数据,而不是直接获取它。这个想法与最初的数据加载器 JavaScript 库非常相似。仅适用于默认值AsyncExecutionStrategy仅适用于查询(因此不要期望它适用于突变和订阅)。

您可以提供DataLoaderRegistryin的实例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,逻辑同上,进入DataLoaderRegistryvia@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 回答