在 GraphQL 中,在创建突变以创建作业或更新作业时,我收到以下错误:
Error: Error caused by mis-matched default values for the "id" field of "BaseEntity". The default value from the decorator "null" is not equal to the property initializer value "d548e85d-1c38-47e1-9e80-a98532204b97". Ensure that these values match.
对同一实体的查询不会出现该错误。我的工作实体如下所示:
export enum JobStatusType {
NEW,
STARTED,
FINISHED,
CANCELLED,
}
registerEnumType(JobStatusType, {
name: 'JobStatusType',
description: 'The State of the job.',
});
export enum JobType {
EMERGENCY,
SHORT_NOTICE,
REGULAR,
}
registerEnumType(JobType, {
name: 'JobType',
description: 'The category/type of the job.',
});
@ObjectType({
description:
'Job Entity. This represents any kind of job that is being offered by AGENCY Organization, and potentially fulfilled by a user from a COURIER Organization.',
})
@InputType({ isAbstract: true })
@Entity()
export class Job extends BaseEntity {
@ManyToOne({
entity: () => Location,
cascade: [Cascade.REMOVE, Cascade.PERSIST],
strategy: LoadStrategy.JOINED,
nullable: false,
})
@Field((_type) => Location, { nullable: false })
public pickupCity: Location;
@ManyToOne({
entity: () => Location,
cascade: [Cascade.REMOVE, Cascade.PERSIST],
strategy: LoadStrategy.JOINED,
nullable: false,
})
@Field((_type) => Location, { nullable: false })
public dropoffCity: Location;
@Property({
nullable: false,
comment: 'Pickup Date and Time',
}) // necessary for MikroORM entity
@Field((__type) => Date, {
description: 'Pickup Date and Time',
nullable: false,
}) // necessary for NestJS/Graphql
public pickupTime: Date;
@Property({
nullable: false,
comment: 'Return to source Date and Time',
}) // necessary for MikroORM entity
@Field((__type) => Date, {
description: 'Return to source Date and Time',
nullable: false,
}) // necessary for NestJS/Graphql
public returnTime: Date;
@Property({ type: 'text', nullable: false })
@Field({
description: 'The description of the Items',
nullable: false,
})
public itemsDescription: string;
@Property({ length: 150, nullable: true })
@Field({ description: 'Title of the Job', nullable: true })
public title?: string;
@Property({ type: 'text', nullable: true })
@Field({
description: 'The description of the Job.',
nullable: true,
})
public description?: string;
@Property({ nullable: true }) // necessary for MikroORM entity
@Field((_type) => Boolean, {
description: 'has an incident occured',
nullable: true,
}) // necessary for NestJS/Graphql
public hasIncident?: boolean;
@Property({ type: 'number', nullable: true })
@Field({
description: 'The daily rate for the job as proposed by Agency.',
nullable: true,
})
public dailyRate?: number;
@Property({ type: 'number', nullable: true })
@Field({
description: 'The fixed rate for the job as proposed by Agency.',
nullable: true,
})
public fixedRate?: number;
@Property({ type: 'number', nullable: true })
@Field({
description: 'The kickoff fee for the job as proposed by Agency.',
nullable: true,
})
public kickOffFee?: number;
@Property({ type: 'number', nullable: true })
@Field({
description: 'The transportation fee for the job as proposed by Agency.',
nullable: true,
})
public transportationFee?: number;
@Enum({
items: () => Currency,
nullable: true,
type: Enum,
})
@Field((_type) => Currency, {
description: 'Currency for the job as proposed by Agency.',
nullable: true,
})
public clientAgencycurrency?: Currency;
@Property({ nullable: true }) // necessary for MikroORM entity
@Field((_type) => Boolean, {
description: 'is the accomodation booked by courier as proposed by Agency.',
nullable: true,
}) // necessary for NestJS/Graphql
public isAccomodationBookedByCourier?: boolean;
@Property({ nullable: true }) // necessary for MikroORM entity
@Field((_type) => Boolean, {
description: 'is the accomodation paid by courier as proposed by Agency.',
nullable: true,
}) // necessary for NestJS/Graphql
public isAccomodationPaidByCourier?: boolean;
@Property({ type: 'number', nullable: true })
@Field({
description: 'The number of items transported in the job',
nullable: true,
})
public numOfItems?: number;
@Property({ type: 'number', nullable: true })
@Field({
description: 'The total weights of items transported in the job',
nullable: true,
})
public weightfItems?: number;
@Property({ type: 'number', nullable: true })
@Field({
description: 'The number of couriers required to do the job',
nullable: true,
})
public numOfCouriersRequired?: number;
@ManyToOne({
entity: () => Location,
cascade: [Cascade.REMOVE, Cascade.PERSIST],
strategy: LoadStrategy.JOINED,
nullable: true,
})
@Field((_type) => Location, { nullable: true })
public pickupAddress?: Location;
@Property({ type: 'text', nullable: true })
@Field({
description: 'Pickup Address Description',
nullable: true,
})
public pickupAddressDescription?: string;
@ManyToOne({
entity: () => Location,
cascade: [Cascade.REMOVE, Cascade.PERSIST],
strategy: LoadStrategy.JOINED,
nullable: true,
})
@Field((_type) => Location, { nullable: true })
public startAirport?: Location;
@ManyToOne({
entity: () => Location,
cascade: [Cascade.REMOVE, Cascade.PERSIST],
strategy: LoadStrategy.JOINED,
nullable: true,
})
@Field((_type) => Location, { nullable: true })
public dropoffAddress?: Location;
@Property({ type: 'text', nullable: true })
@Field({
description: 'Dropoff Address Description',
nullable: true,
})
public dropoffAddressDescription?: string;
@ManyToOne({
entity: () => Location,
cascade: [Cascade.REMOVE, Cascade.PERSIST],
strategy: LoadStrategy.JOINED,
nullable: true,
})
@Field((_type) => Location, { nullable: true })
public endAirport?: Location;
@Property({
nullable: true,
comment: 'Dropoff Date and Time',
}) // necessary for MikroORM entity
@Field((__type) => Date, {
description: 'Dropoff Date and Time',
nullable: true,
}) // necessary for NestJS/Graphql
public dropoffTime?: Date;
@Property({ type: 'text', nullable: true })
@Field({
description: 'Specific Instructions or Details',
nullable: true,
})
public jobDetails?: string;
@Property({ nullable: true }) // necessary for MikroORM entity
@Field((_type) => Boolean, {
description: 'is car required for the job',
nullable: true,
}) // necessary for NestJS/Graphql
public isCarRequiredForJob?: boolean;
@Property({ nullable: true }) // necessary for MikroORM entity
@Field((_type) => Boolean, {
description: 'is driving license required for the job',
nullable: true,
}) // necessary for NestJS/Graphql
public isDrivingLicenseRequiredForJob?: boolean;
@Enum({
items: () => JobStatusType,
nullable: false,
type: Enum,
default: JobStatusType.NEW,
})
@Field((_type) => JobStatusType, {
description: 'Job Status Type (new, started, finished, cancelled)',
defaultValue: JobStatusType.NEW,
nullable: false,
})
public jobType?: JobType;
@Enum({
items: () => JobStatusType,
nullable: false,
type: Enum,
})
@Field((_type) => JobStatusType, {
description: 'Job Status Type (new, started, finished, cancelled)',
nullable: false,
})
public jobStatusType?: JobStatusType;
@OneToMany({
entity: () => JobAgencyCourierOrganization,
mappedBy: (organizationJob) => organizationJob.job,
orphanRemoval: true,
cascade: [Cascade.PERSIST, Cascade.REMOVE],
strategy: LoadStrategy.JOINED,
})
@Field((_type) => [JobAgencyCourierOrganization], { nullable: true })
public jobAgencyCourierOrganizations?: Collection<JobAgencyCourierOrganization> =
new Collection<JobAgencyCourierOrganization>(this);
@OneToMany({
entity: () => JobClientAgencyOrganization,
mappedBy: (organizationJob) => organizationJob.job,
orphanRemoval: true,
cascade: [Cascade.PERSIST, Cascade.REMOVE],
strategy: LoadStrategy.JOINED,
})
@Field((_type) => [JobClientAgencyOrganization], { nullable: true })
public jobClientAgencyOrganizations?: Collection<JobClientAgencyOrganization> =
new Collection<JobClientAgencyOrganization>(this);
constructor(attributes: {
id?: string;
pickupCity: Location;
dropoffCity: Location;
pickupTime: Date;
returnTime: Date;
itemsDescription: string;
clientAgencycurrency?: Currency;
dailyRate?: number;
description?: string;
dropoffAddress?: Location;
dropoffAddressDescription?: string;
dropoffTime?: Date;
endAirport?: Location;
fixedRate?: number;
hasIncident?: boolean;
isAccomodationBookedByCourier?: boolean;
isAccomodationPaidByCourier?: boolean;
isCarRequiredForJob?: boolean;
isDrivingLicenseRequiredForJob?: boolean;
jobStatusType?: JobStatusType;
jobType?: JobType;
kickOffFee?: number;
numOfCouriersRequired?: number;
numOfItems?: number;
pickupAddress?: Location;
pickupAddressDescription?: string;
startAirport?: Location;
title?: string;
transportationFee?: number;
weightfItems?: number;
}) {
super(attributes?.id);
if (attributes) {
Object.assign(this, attributes);
}
}
}
被引用的 BaseEntity 如下所示:
@ObjectType({ isAbstract: true }) // GraphQL
@InputType({ isAbstract: true }) // GraphQL
@Entity({ abstract: true }) // GraphQL
@Directive('@extends') // GraphQL
@Directive('@key(fields: "id")') // GraphQL
@Filter({
name: 'notDeleted',
cond: { deletedAt: { $eq: null } },
default: true,
}) // This filter (not soft-deleted) is active by default.
@Filter({
name: 'all',
cond: {
$or: [{ deletedAt: { $ne: null } }, { deletedAt: { $eq: null } }],
},
}) // This filter returns all rows (deleted and not deleted).
@Filter({ name: 'deleted', cond: { deletedAt: { $ne: null } } })
export abstract class BaseEntity {
@Field((_type) => ID, { nullable: false, defaultValue: null }) // GraphQL
@PrimaryKey({ type: 'uuid', nullable: false }) // NestJs / MikroORM
public id: string;
@Field((_type) => Date)
@Property({ type: Date, nullable: false })
public createdAt: Date = new Date();
@Field((_type) => Date)
@Property({ onUpdate: () => new Date(), type: Date, nullable: false })
public updatedAt: Date = new Date();
@Property({ default: null, nullable: true })
@Field((_type) => Date, {
description:
'This is not null if the entity is marked as deleted (soft delete).',
nullable: true,
})
public deletedAt?: Date;
constructor(id?: string) {
this.id = id || v4();
}
}
Job 的 InputType,JobInput 定义如下:
@InputType()
export class JobInput extends PickType(
Job,
[
'clientAgencycurrency',
'dailyRate',
'dropoffAddress',
'dropoffAddressDescription',
'dropoffCity',
'dropoffTime',
'endAirport',
'fixedRate',
'hasIncident',
'isAccomodationBookedByCourier',
'isAccomodationPaidByCourier',
'isCarRequiredForJob',
'isDrivingLicenseRequiredForJob',
'itemsDescription',
'kickOffFee',
'numOfCouriersRequired',
'numOfItems',
'pickupAddress',
'pickupAddressDescription',
'pickupCity',
'pickupTime',
'returnTime',
'startAirport',
'transportationFee',
'weightfItems',
],
InputType,
) {
// This needs to be overridden and cannot be obtained from the base.entity.ts via PickType, as this would result in a default value upon initialization.
@Field((_type) => ID, { nullable: false })
public id: string;
}
这是我的突变:
@Mutation((_returns) => Job)
async createJob(
@Info() info,
@CurrentUserContextGql() userContext: UserContext,
@Args('jobInput', {
nullable: false,
type: () => JobInput,
})
jobInput: JobInput,
): Promise<Job> {
// TODO: check for allowed to create first!
const job = await this.jobService.create(userContext, jobInput);
return job;
}
对于其他实体和输入类型,我没有收到此错误。我应该怎么办?