TypeORM插入多对一关联记录时外键为null如何解决
问题原因
外键字段插入为null的核心原因是:你的OrderPeople实体中没有定义orderId、peopleId这两个属性,仅定义了order、people两个关联对象属性。TypeORM做插入映射时,无法识别传入数据里的orderId、peopleId字段对应数据库的order_id、people_id列,所以这两个字段会被默认赋值为null。
你不需要通过关联实体的级联操作插入,完全可以在保持服务拆分、符合SOLID原则的前提下解决问题,有两种可落地方案:
方案1:实体中显式声明外键属性(推荐)
在实体类中把外键列作为普通属性显式定义,同时和已有的@ManyToOne关联绑定,后续直接传id值即可完成插入,不需要查询关联的Order、People实体实例,也不影响你后续需要时访问关联对象。
修改后的实体代码如下:
import { Column, Entity, JoinColumn, ManyToOne, PrimaryGeneratedColumn } from 'typeorm'; import { Order } from './order.entity'; import { People } from '../../people/entities/people.entity'; @Entity('order_people') export class OrderPeople { @PrimaryGeneratedColumn() id: number; // 显式定义order_id外键对应的属性 @Column({ name: 'order_id' }) orderId: number; @ManyToOne(() => Order) @JoinColumn({ name: 'order_id' }) order: Order; // 显式定义people_id外键对应的属性 @Column({ name: 'people_id' }) peopleId: number; @ManyToOne(() => People) @JoinColumn({ name: 'people_id' }) people: People; @Column({ type: 'decimal', precision: 15, scale: 4 }) price: number; @Column({ type: 'int' }) quantity: number; @Column({ type: 'decimal', precision: 15, scale: 4 }) cost: number; }
改完后你原来的插入逻辑不需要做任何调整,直接传入{ peopleId: 1, orderId: 1, price: 122.4533, quantity: 2 }结构的数据就能正确给外键字段赋值。
方案2:插入时直接映射数据库字段名
如果你不想修改实体定义,可以在插入前把数据的key改成数据库表实际的列名,绕过TypeORM的属性映射逻辑直接写入:
// 先把传入的DTO字段映射为数据库实际列名 const insertValues = updatePeopleDto.map(item => ({ order_id: item.orderId, people_id: item.peopleId, price: item.price, quantity: item.quantity, cost: item.price * item.quantity // 注意cost字段是非空的,需要按业务逻辑赋值 })) await this.orderPeopleRepository.createQueryBuilder() .insert() .into(OrderPeople) .values(insertValues) .execute()
注意事项
你当前测试用的插入数据缺少cost字段值,而你实体中cost字段没有配置nullable: true或者默认值,外键问题解决后也会触发数据库非空约束报错,记得按业务规则补全该字段值。
内容的提问来源于stack exchange,提问作者Aslero
相关产品推荐
相关产品推荐

