You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NestJS中TypeORM PostgreSQL @ManyToOne保存违反非空约束问题

问题原因

你在所有实体的关联关系上错误添加了primary: true配置,该配置的作用是将关联外键设为实体复合主键的一部分,而你的三个实体本身都已经通过@PrimaryGeneratedColumn声明了独立的自增主键,冲突的主键配置导致TypeORM处理关联字段映射时逻辑混乱。

差异化表现的原因

Document到Page的关联能正常运行,是因为你在DocumentEntity的@OneToMany关联上额外配置了cascade: true,保存Page实体时TypeORM会自动处理关联Document的主键映射;而Page到Word的关联没有配置cascade,加上错误的primary: true配置,导致TypeORM没有正确将你赋值的page实体的id映射到数据库的pageId字段,最终插入时pageId为空触发非空约束报错。

解决方案
  1. 移除所有关联关系上不必要的primary: true配置,你的场景不需要将关联字段设为主键的一部分。
    修改后的实体关联配置参考如下:

document.entity.ts 调整部分

@OneToMany(() => PageEntity, (page) => page.document, {
  eager: true,
  cascade: true,
})
public pages?: PageEntity[];

page.entity.ts 调整部分

@OneToMany(() => WordEntity, (word) => word.page, {
  eager: true,
  onDelete: 'CASCADE',
})
words?: WordEntity[];

@ManyToOne(() => DocumentEntity, {
  onDelete: 'CASCADE',
})
@JoinColumn()
public document: DocumentEntity;

word.entity.ts 调整部分

@ManyToOne(() => PageEntity, {
  nullable: true,
  onDelete: 'CASCADE',
})
@JoinColumn()
public page!: PageEntity;
  1. 同步数据库表结构:修改实体配置后需要重建表或者执行迁移更新表约束,旧表残留的非空约束依然会导致报错。
  2. (可选)代码优化:不需要查询完整的Page实体即可完成关联赋值,可以直接通过id关联,减少一次数据库查询:
async postWord(pageId: number, word: { text: string }) {
  const wordEntity = new WordEntity();
  wordEntity.text = word.text;
  wordEntity.page = { id: pageId } as PageEntity;
  await this.wordRepository.save(wordEntity);
}

内容的提问来源于stack exchange,提问作者Pierre_T

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 00:06:06