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

Dul*_*leX 4 java graphql graphql-java

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

car.graphqls

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

type Car {
    id: ID!,
    name: String!
}
Run Code Online (Sandbox Code Playgroud)

房子.graphqls

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

type House {
    id: ID!,
    owner: String,
    street: String
}
Run Code Online (Sandbox Code Playgroud)

我搜索了很多,但找不到一种方法来编写两个 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

我发现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)
Run Code Online (Sandbox Code Playgroud)

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

extend Type Query {
    house(id: ID!): House
}
Run Code Online (Sandbox Code Playgroud)

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

Dul*_*leX 12

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

我只想向所有正在寻找答案的人总结最终解决方案,如何在每个文件中创建具有不同查询类型的多个模式文件,并使用 GraphQLQueryResolver 将这些查询类型映射到不同的 Java 组件。

我的 Spring Boot 项目结构

我有两个模式文件 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
}
Run Code Online (Sandbox Code Playgroud)

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

  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);
  }
}
Run Code Online (Sandbox Code Playgroud)

还有第二个...

@Component
public class BQuery implements GraphQLQueryResolver {

  @Autowired
  private BookService bookService;

  public List<Book> getBooks(final int count) {
      return this.bookService.getBooks(count);
  }
}
Run Code Online (Sandbox Code Playgroud)

这些类的名称并不重要。我们也可以只有一个实现 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

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


小智 9

多个架构文件

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

多个解析器

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

错误

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