FieldUndefined 类型的验证错误:类型 'Query' 中的字段 'register' 未定义

Validation error of type FieldUndefined: Field 'register' in type 'Query' is undefined

我是 GrapQL 的新手。我正在尝试将它与 spring 引导一起使用。我可以成功进行查询,它正在 returning 我需要的数据,但我现在想使用突变。我需要在他注册的时候给数据库添加一个use

这是我的 schema.graphqls 文件:

type Token {
    token: String
}
type Register {
    message: String
}
type User {
    username: String!
    firstName: String!
    lastName: String!
    password: String!
    role: String!
}

type Query {
    login(username: String, password: String): Token
}

type Mutation {
    register(input: RegisterUserInput!): Register
}

input RegisterUserInput {
    username: String!
    firstName: String!
    lastName: String!
    password: String!
    role: String!
}

schema {
    query: Query
    mutation: Mutation
}

因此,正如您所见,register 是 Mutation 类型,它与 Query 一样添加到 schema 中。但出于某种原因,它看起来没有进入 Mutation,它只是试图在 Query 中查找类型。

这是我的控制器:

@Autowired
    private UserService userService;

    /**
     * Login the user and return generated token
     * @param query
     * @return String token
     */
    @PostMapping("/login")
    public ResponseEntity<Object> login(@RequestBody String query){
        ExecutionResult executionResult = userService.getGraphQL().execute(query);

        // Check if there are errors
        if(!executionResult.getErrors().isEmpty()){
            return new ResponseEntity<>(executionResult.getErrors().get(0).getMessage(), HttpStatus.UNAUTHORIZED);
        }

        return new ResponseEntity<>(executionResult, HttpStatus.OK);
    }

    /**
 * Create new user and save him to database
 * @param mutation
 * @return String message
 */
@PostMapping("/register")
public ResponseEntity<Object> register(@RequestBody String mutation){
    ExecutionResult executionResult = userService.getGraphQL().execute(mutation);

    // Check if there are errors
    if(!executionResult.getErrors().isEmpty()){
        return new ResponseEntity<>(executionResult.getErrors().get(0).getMessage(), HttpStatus.UNAUTHORIZED);
    }

    return new ResponseEntity<>(executionResult, HttpStatus.OK);
}

正如我所说,登录工作正常,但注册是return我在标题中提到的错误。

我的服务class:

@Value("classpath:graphql-schema/schema.graphqls")
    Resource resource;

    private GraphQL graphQL;

    @Autowired
    private LoginDataFetcher loginDataFetcher;
    @Autowired
    private RegisterDataFetcher registerDataFetcher;

    @PostConstruct
    public void  loadSchema() throws IOException{
    // Get the schema
    File schemaFile = resource.getFile();

    // Parse schema
    TypeDefinitionRegistry typeDefinitionRegistry = new SchemaParser().parse(schemaFile);
    RuntimeWiring runtimeWiring = buildRuntimeWiring();
    GraphQLSchema graphQLSchema = new SchemaGenerator().makeExecutableSchema(typeDefinitionRegistry, runtimeWiring);
    graphQL = GraphQL.newGraphQL(graphQLSchema).build();
}

private RuntimeWiring buildRuntimeWiring() {
    return RuntimeWiring.newRuntimeWiring()
            .type("Query", typeWiring ->
                typeWiring
                    .dataFetcher("login", loginDataFetcher))
            .type("Mutation", typeWiring ->
                typeWiring
                    .dataFetcher("register", registerDataFetcher))
            .build();
}

public GraphQL getGraphQL() {
    return graphQL;
}

我的 LoginDataFetcher:

@Autowired
    private AppUserRepository appUserRepository;

    private JwtGenerator jwtGenerator;

    public LoginDataFetcher(JwtGenerator jwtGenerator) {
        this.jwtGenerator = jwtGenerator;
    }

    @Override
    public TokenDAO get(DataFetchingEnvironment dataFetchingEnvironment) {
        String username = dataFetchingEnvironment.getArgument("username");
        String password = dataFetchingEnvironment.getArgument("password");

        AppUser appUser = appUserRepository.findByUsername(username);

        // If user is not foung
        if(appUser == null){
            throw new RuntimeException("Username does not exist");
        }

        // If the user is fount check passwords
        if(!appUser.getPassword().equals(password)){
            throw new RuntimeException("Incorrect password");
        }

        // Generate the token
        String token = jwtGenerator.generate(appUser);

        return new TokenDAO(token);
    }

RegisterDataFetcher:

@Autowired
    private AppUserRepository appUserRepository;

    @Override
    public RegisterDAO get(DataFetchingEnvironment dataFetchingEnvironment) {
        String username = dataFetchingEnvironment.getArgument("username");
        String firstName = dataFetchingEnvironment.getArgument("firstName");
        String lastName = dataFetchingEnvironment.getArgument("lastName");
        String password = dataFetchingEnvironment.getArgument("password");
        String role = dataFetchingEnvironment.getArgument("role");

        AppUser appUser = appUserRepository.findByUsername(username);

        // Check if username exists
        if(appUser != null){
            throw new RuntimeException("Username already taken");
        }

        AppUser newAppUser = new AppUser(username, password, role, firstName, lastName);

        // Save new user
        appUserRepository.save(newAppUser);

        return new RegisterDAO("You have successfully registered");
    }

我在控制台中遇到的错误:

graphql.GraphQL                          : Query failed to validate : '{
    register(username: "user", firstName: "Bla", lastName: "Blabla", password: "password", role: "DEVELOPER") {
        message
    }
}'

感谢您的帮助。

更新

根据得到的答案,我这样更改了架构文件:

query UserQuery{
    login(username: String, password: String){
        token
    }
}

mutation UserMutation{
    register(input: RegisterUserInput) {
        message
    }
}

input RegisterUserInput {
    username: String!
    firstName: String!
    lastName: String!
    password: String!
    role: String!
}

schema {
    query: UserQuery
    mutation: UserMutation
}

但现在我收到这个错误:

解析类型 'query' 时不存在操作类型 'UserQuery' 解析类型 'mutation'

时,操作类型 'UserMutation' 不存在

那么现在的问题是什么?我怎样才能完成这项工作?

你告诉 GraphQL 你正在请求一个查询,而实际上 register 是一个 Mutation。编写 GraphQL 请求时,查询的语法通常遵循以下格式:

query someOperationName {
  login {
    # other fields
  }
}

编写变更时,您只需指定:

mutation someOperationName {
  register {
    # other fields
  }
}

您可以省略操作名称,但最好包含它。您可能会看到这种格式的示例:

{
  someQuery {
    # other fields
  }
}

在这种情况下,操作 name 和操作 type(查询与突变)都被关闭了。这仍然是一个有效的请求,因为当您离开操作类型时,GraphQL 只是假设您的意思是 query 。来自规范:

If a document contains only one operation, that operation may be unnamed or represented in the shorthand form, which omits both the query keyword and operation name.

所以在你的请求中,GraphQL 假设 register 是一个查询,而实际上它是一个突变,并且它返回一个错误作为结果。

同样,在编写请求时,最好始终包含操作名称和 query/mutation 关键字。