TypeORM用ForeignKey创建一条记录



我有两个实体questionnairessections。问卷有多个部分,所以关系是OneToMany

当我尝试为问卷创建一个新记录时-它工作得很好。我得到一个id,然后创建一个section记录,并在那里引用id。

响应,当我尝试创建一个section时,这是

{
"name": "Section 1",
"questionnaire_id": 1,
"description": "Section 1 description",
"id": 1
}

如您所见,它返回questionnaire_id,但问题是,该记录在DB是questionnaire_id=null。如果我手动改变它,并分配一个id值给它,然后它的工作,我得到我的JSON文档与部分在它。

如果我从DB中获取所有记录,那么我得到这个

[
{
"id": 1,
"name": "Section 1",
"description": "Section 1 description"
}
]

questionnaire_id不存在,因为它是null。😕.

你知道我可能做错了什么吗?我有一种感觉,它与实体关系有关,但不确定究竟是什么。
@Entity({ name: 'questionnaires' })
export class Questionnaire {
@PrimaryGeneratedColumn()
id: number;
@Column({ type: 'varchar', length: 128 })
name: string;
@Column({ type: 'enum', enum: STATUS, default: STATUS.ACTIVE })
status: STATUS;
@OneToMany(() => Section, (section) => section.questionnaire)
@JoinColumn({ name: 'questionnaire_id' })
sections: Section[];
}
@Entity({ name: 'sections' })
export class Section {
@PrimaryGeneratedColumn()
id: number;
@Column({ type: 'varchar', length: 128 })
name: string;
@Column({ type: 'text', default: '' })
description: string;
@ManyToOne(() => Questionnaire, (questionnaire) => questionnaire.sections)
questionnaire: Questionnaire;
}

我们的目标是得到所有的问卷和他们的"部分"。

我想实现的方式是这样的

@Injectable()
export class QuestionnaireService {
constructor(@InjectRepository(Questionnaire) private readonly questionnaire: Repository<Questionnaire>) {}
create(createQuestionnaireDto: CreateQuestionnaireDto) {
return this.questionnaire.save(createQuestionnaireDto);
}
findAll() {
return this.questionnaire.find({
relations: ['sections'],
});
}
}
@Injectable()
export class SectionService {
constructor(@InjectRepository(Section) private readonly sectionRepository: Repository<Section>) {}
create(createSectionDto: CreateSectionDto) {
return this.sectionRepository.save(createSectionDto);
}
findAll() {
return this.sectionRepository.find();
}
}
export class CreateSectionDto {
@ApiProperty({
description: 'Section name',
example: 'Section 1',
})
@IsString()
@IsNotEmpty()
@MaxLength(128)
name: string;
@ApiProperty({
description: 'Relation to the questionnaire',
example: 1,
})
@IsNumber()
questionnaire_id: number;
@ApiProperty({
description: 'Section description',
example: 'Section 1 description',
default: '',
})
@IsString()
@IsOptional()
@MaxLength(512)
description?: string;
}

注。

我检查了这一个TypeORM插入行与外键

但对我不起作用

编辑:

这是运行insert命令

时执行的查询。
query: START TRANSACTION
query: INSERT INTO "sections"("created_at", "updated_at", "name", "description", "questionnaire_id") VALUES (DEFAULT, DEFAULT, $1, $2, DEFAULT) RETURNING "created_at", "updated_at", "id", "description" -- PARAMETERS: ["Section 1","Section 1 description"]
query: COMMIT

我有"created_at";updated_at"字段,但我没有包括在上面的例子中。

因为它是可见的,它包括questionnaire_id,但由于某种原因,值被设置为DEFAULT。没有传递我通过http请求发送的那个

<标题>

解决方案问题是我创建记录的方法。因为我已经建立了一个DB关系,Section的表依赖于Questionnaire的表——TypeORM不允许我用我的FK值创建Section记录。如果我先创建了Questionnaire并将Sections对象分配给它,那么库将自动处理它。

使用上面的配置,下面的行可以正常工作

async create(createQuestionnaireDto: CreateQuestionnaireDto) {
const questionnaire = this.questionnaire.create(createQuestionnaireDto);
const sections = new Section();
sections.name = 'Default Section';
sections.summary = 'Default Section Summary';
sections.questionnaire = questionnaire;
await this.questionnaire.save(questionnaire);
await this.section.save(sections);
return questionnaire;
}

它正在运行的查询是这个

query: START TRANSACTION
query: INSERT INTO "sections"("created_at", "updated_at", "name", "summary", "questionnaire_id") VALUES (DEFAULT, DEFAULT, $1, $2, $3) RETURNING "created_at", "updated_at", "id", "summary" -- PARAMETERS: ["Default Section","Default Section Summary",1]
query: COMMIT

可以看到questionnaire_id没有DEFAULT

如果我想让我的初始方法工作,我不应该使用TypeORM关系装饰器,这是一个非常糟糕的主意。

由于我不经常使用TypeORM,所以我不能完全确定答案,但是你可以看看这个。

所以你可能在定义实体关系时做错了。您正在使用问卷实体中的@JoinColumn

应该在Sections Entity中定义,如下所示:

@Entity({ name: 'sections' })
export class Section {
@PrimaryGeneratedColumn()
id: number;
@Column({ type: 'varchar', length: 128 })
name: string;
@Column({ type: 'text', default: '' })
description: string;
@ManyToOne(() => Questionnaire, (questionnaire) => questionnaire.sections)
@JoinColumn({ name: 'questionnaire_id' })
questionnaire: Questionnaire;
}

答案基于此文档https://typeorm.io/relations#joincolumn-options。希望它能解决你的问题。

编辑:(不相关的可能被弃用,但在官方文档中提到)你确定这样加载关系可以吗?

findAll() {
return this.questionnaire.find({
relations: ['sections'],
});
}

从这里的文档可以看出,他们在做别的事情。

findAll() {
return this.questionnaire.find({
relations: {
sections: true,
},
});
}

编辑2:

所以如果你现在添加一个列到你的section实体像这样,它会工作。

@Entity({ name: 'sections' })
export class Section {
@PrimaryGeneratedColumn()
id: number;
@Column({ type: 'varchar', length: 128 })
name: string;
@Column({ type: 'text', default: '' })
description: string;
@Column({ type: 'number' })
questionnaire_id: number;
@ManyToOne(() => Questionnaire, (questionnaire) => questionnaire.sections)
@JoinColumn({ name: 'questionnaire_id' })
questionnaire: Questionnaire;
}

让我知道这是否有效。

最新更新