使用NestJS+TypeOrm保存关联Transaction的PlanOrder实体时出错
解决TypeORM OneToOne关联保存时的UpdateValuesMissingError错误
问题根源
这个错误是因为OneToOne关联配置不完整,TypeORM在处理关联逻辑时错误触发了空更新操作。具体问题点:
PlanOrder实体的@OneToOne关联缺少@JoinColumn()装饰器,TypeORM无法确定外键存储位置,进而尝试更新Transaction却没有指定更新值。- 未建立
Transaction与PlanOrder的反向关联,TypeORM无法正确识别双向关系逻辑。 save方法未使用await,异步操作未被正确等待执行。
修复步骤
1. 完善PlanOrder实体的OneToOne关联
给transaction字段添加@JoinColumn(),标识该表为关系所有者(数据库表中会生成transactionId外键):
// planOrder.entity.ts import { Media } from 'src/media/media.entity'; import { Entity, PrimaryGeneratedColumn, ManyToOne, OneToOne, CreateDateColumn, UpdateDateColumn, JoinColumn } from 'typeorm'; import { Plan } from './plan.entity'; import { Transaction } from 'src/transaction/entities/transaction.entity'; @Entity() export class PlanOrder { @PrimaryGeneratedColumn() id: number; @ManyToOne(() => Media, (media) => media.id) media: Media; @ManyToOne(() => Plan, (plan) => plan.id) plan: Plan // 修改此处:添加@JoinColumn,关联指向Transaction的反向属性 @OneToOne(() => Transaction, (transaction) => transaction.planOrder) @JoinColumn() transaction: Transaction @CreateDateColumn() createdAt: Date; @UpdateDateColumn() updatedAt: Date; }
2. 在Transaction实体中添加反向关联
给Transaction实体添加对应的OneToOne反向字段,让TypeORM识别完整的双向关系:
// transaction.entity.ts import { Entity, PrimaryGeneratedColumn, Column, OneToOne } from 'typeorm'; import { PlanOrder } from 'src/plan-order/planOrder.entity'; // 根据实际路径调整 @Entity() export class Transaction { @PrimaryGeneratedColumn() id: number; // 保留你的原有字段(amount、description、paymentDate等) // 添加反向关联字段 @OneToOne(() => PlanOrder, (planOrder) => planOrder.transaction) planOrder: PlanOrder; }
3. 正确等待异步保存操作
在service的create方法中给save添加await,确保异步操作执行完成:
// planOrderService.ts async create(body: CreatePlanOrderDto, userId: number) { const transaction = await this.transactionService.create({ amount: body.amount, description: body.description, paymentDate: body.paymentDate, refrenceNumber: body.refrenceNumber, userId }); // 建议同时给media和plan赋值,避免后续出现关联为空的问题 const planOrder = this.planOrderRepository.create({ media: body.media, plan: body.plan, transaction }); try { // 添加await等待保存完成 await this.planOrderRepository.save(planOrder); } catch (error) { console.log('e', error); } }
额外说明
- OneToOne关系必须有且仅有一方添加
@JoinColumn(),该方的数据库表会生成对应外键字段。 - 如果不需要双向关联,也可以省略反向属性,但仍需给
PlanOrder的transaction字段添加@JoinColumn():@OneToOne(() => Transaction) @JoinColumn() transaction: Transaction
内容的提问来源于stack exchange,提问作者morteza mortezaie
相关产品推荐
相关产品推荐

