【问题标题】:Mapping multiple graphQL schema files to separate resolvers - Spring Boot将多个 graphQL 模式文件映射到单独的解析器 - Spring Boot
【发布时间】:2020-06-06 23:32:48
【问题描述】:

我发现很难将查询从一个模式文件中分离出来。我想要这样的东西:

car.graphqls

type Query {
    car(id: ID!): Car
}

type Car {
    id: ID!,
    name: String!
}

house.graphqls

type Query {
    house(id: ID!): House
}

type House {
    id: ID!,
    owner: String,
    street: String
}

我搜索了很多,但找不到编写两个 java 类并在其中一个中实现 getHouse() 和在另一个中实现 getCar() 的方法。

@Component
public class CarQuery implements GraphQLQueryResolver {

    @Autowired
    private CarService carService;

    public List<Car> getCar(final int id) {
        return this.carService.getCar(id);
    }
}

public class HouseQuery implements GraphQLQueryResolver {

    @Autowired
    private HouseService houseService;

    public List<House> getHouse(final int id) {
        return this.houseService.getHouse(id);
    }
}

我发现我正在使用的graphql-java-tools 包将搜索整个项目并找到所有架构文件(以.graphqls 结尾),但我上面显示的代码给了我这个错误:

Caused by: com.coxautodev.graphql.tools.FieldResolverError: No method found with any of the following signatures (with or without one of [interface graphql.schema.DataFetchingEnvironment] as the last argument), in priority order:

  com.example.polls.resolvers.CarQuery.house(~count)
  com.example.polls.resolvers.CarQuery.getHouse(~count)

我还发现了一些建议,即我只需要在架构文件中包含一个根查询,并在架构文件中扩展所有其他查询类型。我试图写信给house.graphqls 这样的东西,但失败了:

extend Type Query {
    house(id: ID!): House
}

有没有办法告诉 graphql 和 java 我想将哪个模式文件映射到哪个 java 解析器文件?

【问题讨论】:

  • 您的项目是否使用单个 graphqls 文件?如果没有,你应该先确保它。
  • 是的,如果我将所有查询放在一个模式文件中,并且我只保留一个包含所有必需方法的 GraphQLQueryResolver,它就可以工作。我发现与该主题相关的文档和示例很少。所有示例通常都集中在一个模式文件上。在两个模式文件上找不到任何东西,我认为能够在多个模式文件上拆分查询非常有用。项目可能会变得非常大,将它们全部保存在一个架构文件中并不方便。
  • 您说它适用于一个模式文件和一个大解析器,但它适用于一个模式文件和几个小解析器吗?这就是我的graphql项目的设置方式,所以我们应该能够做到这一点。从日志来看,graphql-java-tools 似乎正在解析您的 graphqls 文件,但找不到您的 HouseQuery 解析器。
  • @DulleX 你找到解决方案了吗?我遇到了类似的问题。
  • @Saloo 不幸的是,不。我只是用 Spring 研究 graphql,几天后我放弃了,因为我无法让它与更多的模式文件和更多的解析器一起工作,我可以'没有理由深入了解它,因为我认为,在较大的项目中,使用一个模式文件和一个解析器是不可能进行代码维护的。

标签: java graphql graphql-java


【解决方案1】:

感谢 AllirionX。您的回答很有帮助。

我想为所有正在寻找答案的人总结一下最终解决方案,如何创建多个架构文件,每个架构文件中都有单独的查询类型,并使用 GraphQLQueryResolver 将这些查询类型映射到不同的 Java 组件。

My Spring Boot project structure

我有两个架构文件 A.graphqls 和 B.graphqls。

A.graphqls
---------------
type Person {
  id: ID!,
  name: String
}

type Query {
  getPerson(id: Int):Person
}

type Mutation {
  createPerson(name: String):Int
}

B.graphqls
---------------
type Book {
  id: ID!,
  title: String,
  owner: Person
}

extend type Query {
  getBooks(count: Int):[Book]
}

extend type Mutation {
  deleteBook(id: Int):Int
}

schema {
  query: Query,
  mutation: Mutation
}

我将解释我学到的关于我们需要遵循的关于这个主题的规则(我不保证这一切都是必要的,但这就是我设法让它按照我想要的方式工作的方式)。

  1. 这里的关键是只有一个模式定义。在哪个文件(A.graphqls 或 B.graphqls 或 C.graphqls...)中并不重要 - 例如,我将其添加到底部的 B.graphqls 文件中。

  2. 另外,一个文件中只能有一个“类型查询”定义。在所有其他模式文件中,您将需要使用“扩展类型查询”来扩展该类型(是的,我知道,现在这很有意义......)。在哪个模式文件中为不相关的 Query 进行主要定义。本段中的所有内容也适用于突变。

  3. 您可以在另一个 .graphqls 文件中使用一个 .graphqls 文件中定义的类型。它会得到认可。所以,在这个例子中,你可以在 B.graphqls 中使用 Person 类型引用。

Java 解析器:

import com.coxautodev.graphql.tools.GraphQLQueryResolver;
import graphql.demo.model.Person;
import graphql.demo.service.PersonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
public class AQuery implements GraphQLQueryResolver {

  @Autowired
  private PersonService personService;

  public Person getPerson(final int id) {
      return this.personService.getPerson(id);
  }
}

第二个...

@Component
public class BQuery implements GraphQLQueryResolver {

  @Autowired
  private BookService bookService;

  public List<Book> getBooks(final int count) {
      return this.bookService.getBooks(count);
  }
}

这些类的名称并不重要。我们也可以只有一个实现 GraphQLQueryResolver 的类,我们可以实现来自 A.graphqls 和 B.graphqls 文件的所有查询方法(getBooks() 和 getPerson() 方法)。只要我们实现了所有方法,我们在哪个解析器类中实现它并不重要,graphql-java 会找到它。 这同样适用于使用 GraphQLMutationResolver 的突变。

我的 github 上有完整的工作示例(MySQL、Spring Boot、React with Apollo 客户端),因此您可以查看。还有用于生成项目中使用的数据库的 mysql 脚本。有很多表,但只是为了测试目的,重要的是我上面解释的文件结构和文件。如果您对客户端应用程序不感兴趣,当然可以使用 graphiql 对其进行测试。

https://github.com/dusko-dime/spring-react-graphql

希望这对某人有所帮助,并感谢您再次帮助我:)

【讨论】:

    【解决方案2】:

    多个架构文件

    Graphql-java-tools 将找到所有.graphqls 文件以构建模式实例。多个架构文件开箱即用。

    多个解析器

    每个解析器组件必须实现GraphQLQueryResolverGraphQLMutationResolver 并且可以被spring boot 扫描。确保它有一个@Component 注释并且在一个弹簧@ComponentScan basePackages 中。

    错误

    No method found with any of the following signature 表示 graphql-tools 无法找到具有与签名匹配的方法的解析器组件。在这种情况下,HouseQuery 解析器缺少 @Component 注释。

    【讨论】:

      【解决方案3】:

      您的解析器名称也可能有问题 请确保您指定的解析器方法名称与您在 GraphQL Schema 中定义的名称相同

      【讨论】:

        猜你喜欢
        • 2019-04-27
        • 2017-07-02
        • 1970-01-01
        • 2016-01-27
        • 2019-07-08
        • 2021-05-19
        • 1970-01-01
        • 2021-12-14
        • 2018-03-15
        相关资源
        最近更新 更多