GraphQl Java,我如何盲目地 return 与查询和处理子 类 的问题中的对象关联的所有变量

GraphQl Java, How can I blindly return all variables associated with an object from query and question on handling sub classes

我是 GraphQL 的新手,我目前正在使用 GraphQL-SPQR 将 GraphQL API 实现到已建立的 Java 代码中,我 运行从分层 classes.

中提取数据时出现问题

我运行关注的问题如下。

首先,如果有一种简单的方法可以获取与返回节点关联的所有数据,我不会。如果有的话,这对我更复杂的 classes 最有用。

其次,当方法returns 是抽象class 时,我似乎只能请求抽象class 上的变量。我确定这应该是可能的,我只是用头撞墙。

举个简单的例子

public abstract class Animal {
   private String name;
   private int age;

   // Constructor

   @GraphQLQuery(name = "name")
   public String getName() {
       return name;
   }

   // Age getter
}


public class Dog extends Animal {
   private String favouriteFood;

   // Constructor

   @GraphQLQuery(name = "favouriteFood")
   public String getFavouriteFood() {
       return favouriteFood;
   }
}


public class Database {
    @GraphQLQuery(name = "getanimal")
    public Animal getAnimal(@GraphQLArgument(name = "animalname") String animalname) {
        return database.get(name);
    }
}

所以在我的第一个问题中,我目前正在查询的是。 “{animalname(name: \"Daisy\") {name age}}” 这按预期工作正常。如果你想象 class 然而有 10 个变量,我只想写出下面的等价物而不必查找它们。 “{节点(名称:\"Daisy\"){ALL}}” 这可能吗?

关于我的第二个问题。 下面的查询会抛出一个错误('Field 'favouriteFood' in type 'Animal' is undefined')

"{animalname(name: \"Bones\") {name age favouriteFood}}"

同样(阅读 https://graphql.org/learn/queries/ 的内联片段)

"{animalname(name: \"Bones\") {name age ... on Dog{favouriteFood}}}"

抛出错误 Unknown type Dog

这很烦人,因为我有许多子 class 可能会被退回,并且可能需要以不同的方式处理。我想我可以理解为什么会发生这种情况,因为 GraphQL 不知道真正的 class 是什么,只有我返回的超级 class。不过我想知道是否有办法解决这个问题。

最终,虽然我可以通过简单地将所有数据序列化为 JSON 并将其发回来解决这两个问题,但它有点摆脱了 GraphQL 的意义,我宁愿找到一个替代解决方案。

感谢您的任何回复。 如果这些是基本问题,我们深表歉意。

回答我自己的问题以帮助遇到此问题的其他人。

摘要class需要包含@GraphQLInterface,如下图

@GraphQLInterface(name = "Animal ", implementationAutoDiscovery = true)
public abstract class Animal {
   private String name;
   private int age;

   // Constructor

   @GraphQLQuery(name = "name")
   public String getName() {
       return name;
   }

   // Age getter
}

下面的代码是经过多次求解后发现的,由SPQR的创建者创建。实际上,在设置模式时,您需要声明一个接口映射策略。下面的代码可以被批量复制,只需要将 "nodeQuery" 变量替换为您正在使用的服务以包含您的“@GraphQLQuery”和“@GraphQLMutation”方法。

final GraphQLSchema schema = new GraphQLSchemaGenerator()
                .withInterfaceMappingStrategy(new InterfaceMappingStrategy() {
                    @Override
                    public boolean supports(final AnnotatedType interfase) {
                        return interfase.isAnnotationPresent(GraphQLInterface.class);
                    }

                    @Override
                    public Collection<AnnotatedType> getInterfaces(final AnnotatedType type) {
                        Class clazz = ClassUtils.getRawType(type.getType());
                        final Set<AnnotatedType> interfaces = new HashSet<>();
                        do {
                            final AnnotatedType currentType = GenericTypeReflector.getExactSuperType(type, clazz);
                            if (supports(currentType)) {
                                interfaces.add(currentType);
                            }
                            Arrays.stream(clazz.getInterfaces())
                                    .map(inter -> GenericTypeReflector.getExactSuperType(type, inter))
                                    .filter(this::supports).forEach(interfaces::add);
                        } while ((clazz = clazz.getSuperclass()) != Object.class && clazz != null);
                        return interfaces;
                    }
                }).withOperationsFromSingleton(nodeQuery)// register the service
                .generate(); // done ;)
        graphQL = new GraphQL.Builder(schema).build();

由于这个解决方案需要一些搜索,我将很快开始写博客,介绍我偶然发现的其他解决方案。

关于仅 returns 所有结果的查询。这在 GraphQL 中是不可能的。我可能会写的一种解决方法是有一个端点 returns JSON 整个对象和对象的名称,然后我可以使用 ObjectMapper 将其转换回来。

我希望这对其他人有帮助。我仍在寻找第一个问题的答案,并会在找到答案后更新此 post。