在插入 TypeORM 和 TypeGraphQL 时, ({nullable: true}) 选项去了哪里,有什么区别?

Pet*_*ray 1 typeorm typegraphql

我正在使用一个同时使用 TypeORM 和 Type-GraphQL 的服务器应用程序。

 @Field({ nullable: true })
    @Column({ nullable: true })
    url?: string; 
Run Code Online (Sandbox Code Playgroud)

当我运行 GraphQL 查询(使用 Apollo Studio)时,有时查询会因具有空值而返回错误,而有时在添加新值时突变会失败。

我测试了多种变体,但得到的结果不一致,将以奇怪的方式被拒绝。我研究了它,发现了从删除 node_modules 到删除数据库的建议,所以我决定应该弄清楚每个装饰器中的 null 设置的作用。

{ nullable: true }放入the@field()或 the@column()和不应该简单地放入?类型定义中工作之间有什么区别?

我还将我的@InputType()@Entity()类分成单独的文件,所以我是否也需要@field()在输入中使用相同的值?

完整示例:

实体

import { Field, ID, ObjectType } from "type-graphql";
import { BaseEntity, Column, Entity, PrimaryGeneratedColumn } from "typeorm";

@Entity()
@ObjectType()
export class Click extends BaseEntity{
    
    @Field(type => ID)
    @PrimaryGeneratedColumn("uuid")
    id: string;

    @Field(type => ID)
    @Column({ nullable: true })
    clickId?: string; 

    @Field({ nullable: true })
    @Column({ nullable: true })
    url?: string; 
}
Run Code Online (Sandbox Code Playgroud)

输入

import { MaxLength } from "class-validator";
import { Field, ID, InputType } from "type-graphql";
import { Click } from '../entity/Click';

@InputType()
export class ClickInput implements Partial<Click> {

  //omitted the id field because it's generated on the server 
  
  @Field(type => ID)
  clickId: string; 

  @Field({ nullable: true })
  @MaxLength(256)  
  url: string; 
Run Code Online (Sandbox Code Playgroud)

旋转变压器

import {
  Arg, Mutation,
  Query,
  Resolver
} from "type-graphql";
import { Service } from "typedi";
import { Click } from "../entity/Click";
import { ClickInput } from "../input/ClickInput";
import { ClickService } from "../service/ClickService";

@Service() 
@Resolver(of => Click)
export class ClickResolver {
  constructor(
    // constructor injection of a service
    private readonly clickService: ClickService, 
  ) {}   

  @Query( returns => [Click])
  async clicks() {    
    return this.clickService.list()
  }

  @Query( returns => Click, { nullable: true })  
  async click(@Arg("clickId") clickId: string) {
    return this.clickService.findById(clickId)
  }
  @Mutation( _type => Click )
  async createClick(@Arg("data") data: ClickInput): Promise<Click> {
    return this.clickService.create(data)
  }
  


 }
Run Code Online (Sandbox Code Playgroud)

服务

import { Service } from "typedi";
import { DeleteResult } from "typeorm";
import { InjectRepository } from "typeorm-typedi-extensions";
import { Click } from "../entity/Click";
import { ClickRepository } from "../repo/ClickRepo";


@Service()
export class ClickService {
  constructor(
    @InjectRepository(Click)
    private readonly clickRepository: ClickRepository
  ) {}


  async findById(clickId: string, relations: string[] = []) {
    return this.clickRepository.findOne({
      where: {
        clickId,
      },
      relations: relations,
    });
  }

  async create(params: Partial<Click>): Promise<Click> {
    const u = this.clickRepository.create(params);
    return this.update(u);
  }

  async update(Click: Click): Promise<Click> {
    return this.clickRepository.save(Click);
  }

  async delete(Click: Click): Promise<DeleteResult> {
    return this.clickRepository.delete(Click)
  }

  async list() {
    return this.clickRepository.find()
  }
}
Run Code Online (Sandbox Code Playgroud)

Dem*_*xel 5

如果你想要一个值为空,你应该把它放在两者上。

{ nullable: true }typeorm ( @Entity) 中表示允许数据库存储null值。否则,您将无法在数据库的该列中保存空值。

{ nullable: true}in type-graphql( @Field) 表示由 生成的模式TypeGraphQL将允许该字段为null。否则,在查询时,您可能会收到 的错误Cannot return null for non-nullable field EntityName.fieldName


澄清一下,GraphQL 架构可能如下所示:

type Click {
    id: ID!
    clickId: ID!
    url: String
}
Run Code Online (Sandbox Code Playgroud)

请注意,它url没有 a,!所以它不是必需的,但clickId它有,所以如果传递一个值,您将遇到问题null


至于你的输入类型,你想允许传递一个null值吗?clickId如果是这样,您也希望它nullable: true位于ClickInput. 例如,如果您始终需要clickId创建一个但null后来创建的,那么您可以将其省略以要求输入clickId为非空。

  • 我自己无法更好地解释它。很好的答案! (2认同)