如何解决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个请求:
-
childDataLoader.loadMany({1,5})
-
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()));
};
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。