首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >DataLoader批量装载错误(MyBatis,JavaEE)

问DataLoader批量装载错误(MyBatis,JavaEE)
EN

Stack Overflow用户
提问于 2020-08-28 08:50:34
回答 1查看 234关注 0票数 3

我的产品中有graphql,禁止共享代码。我使用,就像ORM使用MyBatis一样。

代码语言:javascript
复制
<dependency>
     <groupId>com.graphql-java-kickstart</groupId>
     <artifactId>graphql-java-servlet</artifactId>
     <version>9.2.0</version>
</dependency>

启用BatchLoading之后,我发现graphQL DataLoader混淆了批处理请求实体的位置。此外,如果查看futureCacheMap,很容易检查,您会发现Key(Id)和Value(实体)有不同的Id。

调试后,我没有找到graphQL如何在batchLoading (1000PSC)之后解析实体。所以我决定我应该有一些排序,所以我实现了它,但它没有解决问题。

例如:我有Parent.class,里面有孩子。

代码语言:javascript
复制
class Parent {
    private Long id;
    private List<Long> childsIds;
}

我有ChildDataloader

代码语言:javascript
复制
private BatchLoader<Long, Child> buildBatchLoader() {
    return list -> > CompletableFuture.supplyAsync(() -> childService.findByIds(list));                
    }

private DataLoader<Long, Child> buildDataLoader(BatchLoader batchLoader) {
    DataLoaderOptions options = DataLoaderOptions.newOptions();
    options.setMaxBatchSize(1000);
    return new DataLoader<Long, Child>(batchLoader, options);
    }
}

我有ChildsFetcher,在这里我调用了dataLoader.loadMany()

代码语言:javascript
复制
public class ChildsFetcher implements DataFetcher<CompletableFuture<List<Child>>>{

    private static final String PK_FIELD_NAME = "childsIds";

    @Override
    public CompletableFuture<List<LoadDefinitionDTO>> get(DataFetchingEnvironment environment) {
        GraphQLContext context = environment.getContext();
        DataLoaderRegistry dataLoaderRegistry = context.getDataLoaderRegistry().orElseThrow(
                () -> new DalException("there was no dataLoaderRegistry in context", Response.Status.INTERNAL_SERVER_ERROR)
        );
        List<Long> childsIds = getParentFieldValue(environment, PK_FIELD_NAME , List.class);

        DataLoader<Long, Child> childDataLoader = dataLoaderRegistry.getDataLoader("childDataLoader");
        return childDataLoader.loadMany(childsIds)
    }
}

例如,我有两个父母,每个有3个孩子。

代码语言:javascript
复制
parents: [
 {
   "id": 1
   "childIds": {1,3,5}
 },
 {
   "id": 2
   "childIds": {2,4,6}
 }
]

因此,在获取器中,我将有两个请求:

  1. childDataLoader.loadMany({1,3,5})

  1. childDataLoader.loadMany({2,4,6})

在Dataloader中,它将只有一个(如预期的那样),但是查看I的顺序(我无法控制它):

代码语言:javascript
复制
childService.findByIds({1,3,5,2,4,6})

在产出中,我将收到:

代码语言:javascript
复制
"data": {
    "parents": [
      { 
        "id": 1,
        "childs": [
          {
            "id": 1,
          },
          {
            "id": 2,
           },
          {
            "id": 3,
           }
       },
      { 
        "id": 2,
        "childs": [
          {
            "id": 4,
          },
          {
            "id": 5,
           },
          {
            "id": 6,
           }
       }
      ]
     }
   ]
}
EN

回答 1

Stack Overflow用户

发布于 2020-08-28 10:54:48

您的回答顺序必须与请求的顺序相同,如果ORM对sql响应进行排序,只需在从ORM获得响应后将其恢复到DataLoader中,例如:

代码语言:javascript
复制
 private BatchLoader<Long, Child> buildBatchLoader() {
   return list -> CompletableFuture.supplyAsync(() -> 
                   childService.findByIds(list).stream()
                     .sorted(Comparator.comparingLong(entity -> 
                             list.indexOf(entity.getId())))
                     .collect(Collectors.toList()));
 };   
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63630507

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档