如何用graphql-jpa java解决graphql n + 1问题?

时间:2017-12-06 13:03:35

标签: graphql-java

我在我的一个应用程序中面临graphql WebDriverWait wait = new WebDriverWait(driver, 30); wait.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(By.xpath("//iframe[@name='InlineDialog1_Iframe or @id='InlineDialog1_Iframe']"))); 问题,我在java中使用带有restful webservice的graphql。我使用n+1schemagen-graphql连接到我的oracle db。 我看到了很多帖子,但大部分答案都是spring-data-jpa实施。任何与java相关的东西都会很好。

1 个答案:

答案 0 :(得分:10)

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

  1. 在解析父字段时(即在父字段的DataFetcher中)预取您需要的内容。您可以通过检查DataFetchingFieldSelectionSet来预先确切地查看请求的子字段。 如果预取数据自然不适合结果对象,则可以将其存储在LocalContext中,并在解析子字段值时使用它。在this blog post
  2. 中很好地解释了这种方法
  3. 已弃用方法,使用@Batched并使用BatchedExecutionStrategy为您的数据提取程序添加注释。
    此选项易于理解和使用,但与BatchedExecutionStrategy绑定,并且在处理空值时不完全遵守规范。
    令人遗憾的是文档记录很差(如上所述,已弃用),但归结为:
    1. 使用@Batched
    2. 注释DataFetcher#get方法
    3. 在该数据提取器中,DataFetchingEnvironment#getSource将始终返回源对象列表(而不是一个)。
    4. 这样的数据提取器必须始终返回结果列表(与源列表长度相同)。这允许以简单方式批量加载对象。一个明显的例子是立即从关系数据库加载许多行:
  4. 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仅适用于查询(因此不要指望它适用于突变和订阅)。尽管使用起来比较困难,但这个选项已有详细记录,应该是首选。
    2. 您可以在DataLoaderRegistry中提供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-SPQR生成GraphQL API。这是使用@Batched的{​​{3}}。

      对于DataLoader,逻辑与上面相同,您可以通过DataLoaderRegistry注释进入@GraphQLEnvironment

      @GrapgQLQuery
      public CompletableFuture<Author> author(@GraphQLContext Article article, @GraphQLEnvironment ResolutionEnvironment env) {
          return env.dataFetchingEnvironment.getDataLoader("authors").load(article.getAuthorId())
      }
      

      我可能还会添加一个专门的注释,例如@DataLoader("authors"),用于直接注入加载器。