将多个 graphQL 模式文件映射到单独的解析器 - Spring 引导

Mapping multiple graphQL schema files to separate resolvers - Spring Boot

我发现很难将查询与一个模式文件分开。我想要这样的东西:

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 解析器文件?

多个架构文件

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

多个解析器

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

错误

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

感谢 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. 此外,一个文件中只能有一个 "type Query" 定义。在所有其他模式文件中,您将需要使用 "extend type Query" 扩展该类型(是的,我知道,现在这很有意义......)。您在哪个架构文件中为不相关的查询执行主要定义。本段中的所有内容也适用于突变。

  3. 您可以在另一个 .graphqls 文件中使用一个 .graphqls 文件中定义的类型。它会得到认可。因此,在此示例中,您可以在 B.graphqls.

  4. 中使用 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);
  }
}

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

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

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

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

您的解析器名称也可能存在问题 请确保您指定的 Resolver 方法名称与您在 GraphQL Schema

中定义的名称相同