DataLoader批量加载错误MyBatis,JavaEE

问题描述

我的产品中有graphql,并且禁止共享代码。我使用的是graphql-java-servlet,因为ORM使用的是MyBatis。

<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(Entity)具有不同的ID。

调试后,我找不到在批处理加载(1000 psc)后graphQL如何解析实体的方式。因此,我决定应该进行一些订购,因此我实施了订购,但未能解决问题。

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

class Parent {
    private Long id;
    private List<Long> childsIds;
}

我有ChildDataLoader

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()

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)
    }
}

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

parents: [
 {
   "id": 1
   "childIds": {1,3,5}
 },{
   "id": 2
   "childIds": {2,4,6}
 }
]

由于在fetcher中,我将有2个请求:

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

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

DataLoader中,它只会是一个(如预期的那样),但请查看ID的顺序(我无法控制它):

childService.findByIds({1,5,2,6})

输出中,我将收到:

"data": {
    "parents": [
      { 
        "id": 1,"childs": [
          {
            "id": 1,},{
            "id": 2,{
            "id": 3,}
       },{ 
        "id": 2,"childs": [
          {
            "id": 4,{
            "id": 5,{
            "id": 6,}
       }
      ]
     }
   ]
}

解决方法

答案的顺序必须与请求的顺序相同, 如果ORM对sql响应进行了排序,请在从ORM获得响应后,将其重新放入DataLoader中,例如:

 private BatchLoader<Long,Child> buildBatchLoader() {
   return list -> CompletableFuture.supplyAsync(() -> 
                   childService.findByIds(list).stream()
                     .sorted(Comparator.comparingLong(entity -> 
                             list.indexOf(entity.getId())))
                     .collect(Collectors.toList()));
 };   
    
         
                     

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...