GraphQL регистрирует новый тип проводки с аргументом для сборщика данных - PullRequest
0 голосов
/ 03 апреля 2020

Имея схему GraphQL:

type TypeA {
   id: ID,
   name: String,
   other: TypeC
}

type TypeB {
   id: ID,
   name: String,
   other: TypeC
}

Как мне реализовать проводку типа C независимо от типа исходного объекта? Я знаю, что могу сделать:

RuntimeWiring.newRuntimeWiring()
  .type(TypeRuntimeWiring.newTypeWiring("TypeA")
    .dataFetcher("other", dataFetcher_typeC.get())
  .type(TypeRuntimeWiring.newTypeWiring("TypeB")
    .dataFetcher("other", dataFetcher_typeC.get())
  .build()

, но тогда сборщик данных зависит от типа исходного объекта:

DataFetcher<CompletableFuture<Collection<TypeC>>> get() {
  return dataFetchingEnvironment -> {
    <??> sourceObj = dataFetchingEnvironment.getSource();
    return getObject(sourceObj.someProperty);
  };
}

Учитывая, что оба POJO (TypeA и TypeB) имеют поле ссылки для Type C, как разрешить поле Тип C по заданной ссылке, а не по исходному объекту?

Ответы [ 2 ]

0 голосов
/ 24 апреля 2020

Из документации здесь

dataFetchingEnvironment предоставляет метод getExecutionStepInfo (), который возвращает объект ExecutionStepInfo. Оттуда вы можете получить родительскую информацию.

ExecutionStepInfo executionStepInfo = environment.getExecutionStepInfo();
ExecutionStepInfo parentInfo = executionStepInfo.getParent();
GraphQLObjectType parentType = (GraphQLObjectType) parentInfo.getUnwrappedNonNullType();

// parentType.getName() returns you "TypeA" or "TypeB"
0 голосов
/ 04 апреля 2020

Я на самом деле выяснил два возможных решения проблемы:

  1. При определении новой проводки, получите исходный объект и из него поле. Вызовите метод dataFetcher с параметром, как обычный метод java:
  2. Внутри средства извлечения данных получите имя поля из DataFetcherEnvironment. Используйте отражение, чтобы получить поле от исходного объекта

Пример # 1:

RuntimeWiring.newRuntimeWiring()
  .type(TypeRuntimeWiring.newTypeWiring("TypeA")
    .dataFetcher("other", environment -> {
        TypeA sourceObj = environment.getSource();
        return dataFetcher_typeC.get(sourceObj.other)})
  .type(TypeRuntimeWiring.newTypeWiring("TypeB")
        TypeB sourceObj = environment.getSource();
        return dataFetcher_typeC.get(sourceObj.other)})
  .build()

Пример # 2:

DataFetcher<CompletableFuture<Collection<TypeC>>> get() {
  return dataFetchingEnvironment -> {
    Field  declaredField = dataFetchingEnvironment.getSource().getClass()
                  .getDeclaredField(dataFetchingEnvironment.getField().getName());
    declaredField.setAccessible(true);

    String value = (String) declaredField.get(dataFetchingEnvironment.getSource());
    return getObject(sourceObj.someProperty);
  };
}

Второй вариант выглядит лучше, но все еще не уверен если это правильный подход.

...