0

我是 GraphQL 的新手,我目前正在使用 GraphQL-SPQR 将 GraphQL API 实现到已建立的 Java 代码中,并且在从分层类中提取数据时遇到了几个问题。

我遇到的问题如下。

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

其次,当一个方法返回一个抽象类时,我似乎只能请求抽象类上的变量。我相信这应该是可能的,我只是把头撞在墙上。

作为一个简单的例子

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}}" 这可以正常工作。但是,如果您想象该类有 10 个变量,我只想能够编写与以下内容等效的内容,而无需查找它们。"{node(name: \"Daisy\") {ALL}}" 这可能吗?

关于我的第二个问题。以下查询引发错误('Animal' 类型中的'Field 'favouriteFood' is undefined')

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

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

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

抛出错误未知类型 Dog

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

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

感谢您的任何回复。抱歉,如果这些是基本问题。

4

1 回答 1

2

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

抽象类需要包含@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();

由于这个解决方案花了一些时间,我很快就会用我偶然发现的其他解决方案开始一个博客。

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

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

于 2019-06-26T09:14:08.687 回答