跳到主要内容

Mutation

GraphQL Input介绍

在GraphQL中,查询返回的GraphQLObject,即任意形状的动态对象;然而,如果修改操作接受对象参数,必须是GraphQLInput,即固定形状的静态对象。

可参考GraphQLInput以了解更多。

以附带例子中的GraphQL声明文件为例schema.graphqls

type Book implements CommonEntity { ❶
id: Long!
name: String!
edition: Int!
price: BigDecimal!
store: BookStore
authors: [Author!]!
createdTime: LocalDateTime!
modifiedTime: LocalDateTime!
tenant: String!
}

input BookInput { ❷
id: Long
name: String!
edition: Int
price: BigDecimal!
storeId: Long
authorIds: [Long!]!
}

...省略其他代码...
  • type关键字声明的类型是表达任意形状数据结构的动态类型,用作GraphQL的输出类型

  • input关键字声明的类型是表达固定形状数据结构的静态类型,用作GraphQL的输入类型

定义Jimmer Input DTO

Jimmer的Input DTO在保存指令/InputDTO中有非常详细的介绍,本文不做赘述。

Jimmer提供了两种定义Input DTO的方式

采用DTO语言可以非常高效地达到我们的目标,所以本文采用这种方式。

  1. 在实体定义所在项目中,建立目录src/main/dto

  2. src/main/dto下,按实体类型所处的包路径建立子目录com/yourcompany/yourproject/model

  3. 在上一步建立的目录下,建立文件Book.dto,文件必须和实体类同名,扩展名必须为dto

  4. 编辑此文件,利用DTO语言,定义Book实体的各种DTO形状

    Book.dto
    input BookInput {

    #allScalars(Book)

    id(store)

    id(authors) as authorIds
    }

    ...省略其他DTO定义...

编译完成后,将会自动生成如下Input DTO

BookInput.java
@GeneratedBy(file = "<your_project>/src/main/dto/Book.dto")
public class BookInput implements Input<Book> {

@Nullable
private Long id;

private String name;

private int edition;

private BigDecimal price;

@Nullable
private Long storeId;

private List<Long> authorIds;

@Override
public Book toEntity() {
......
}

...省略其他成员...
}
  • BookInput类实现了接口org.babyfish.jimmer.Input,该接口支持toEntity方法,可以将当前Input DTO对象转化为Jimmer动态实体对象。

  • ❷ 实现Input.toEntity方法

实现GraphQL mutation

BookStoreService.java
package com.example.business;

import org.springframework.graphql.data.method.annotation.Argument;
import org.springframework.graphql.data.method.annotation.MutationMapping;
import org.springframework.stereotype.Controller;

...省略其他导入...

@Controller
public class BookStoreService {

private final BookStoreRepository bookStoreRepository;

public BookStoreService(BookStoreRepository bookStoreRepository) {
this.bookStoreRepository = bookStoreRepository;
}

@MutationMapping
@Transactional
public Book saveBook(
@Argument BookInput input ❷
) {
// `save(input)`是`save(input.toEntity())`的简写方式
return bookRepository.save(input);
}
}
  • ❶ 使用注解@org.springframework.graphql.data.method.annotation.MutationMapping

  • ❷ 使用静态Input DTO类型BookInput,让用户只能传递规定形状的数据结构,以符合GraphQLInput的规范

  • 保存指令,一句话保存任意形状的数据结构

    这里的bookRepository.save(input),其实是bookRepository.save(input.toEntity())的简写。

    提示

    无论BookInput类型所定义数据结构简单还是相对复杂,都可以一句话保存。这是保存指令这个功能的核心价值。