使用TypeORM与NestJS处理一对多关系时PostgreSQL存数报错求助
解决UpdateValuesMissingError错误的方案
错误原因
TypeORM处理关联实体(如customer、products)时,若直接传入无主键(id)的完整实体对象,会默认尝试执行UPDATE操作,但因缺少主键和更新值,触发该错误。你的请求中传入的customer和products都是无id的全新对象,代码未先保存这些关联实体就直接传给Order的create/save方法,导致TypeORM逻辑混乱。
具体修复步骤
1. 调整CreateOrderDto(按业务需求选择)
场景A:关联已有客户/产品(更常见)
用ID替代完整实体对象,避免不必要的新建操作:
export class CreateOrderDto { @IsString() @IsNotEmpty() @Length(5, 400) public description: string; @IsNotEmpty() @IsNumber() @IsPositive() public amount: number; @IsNotEmpty() @IsString() public paymentMethod: string; @IsOptional() @IsString() public customizeName: string; @IsOptional() @IsString() public weight: string; @IsNotEmpty() @IsNumber() public customerId: number; // 替换原customer字段,用客户ID @IsNotEmpty() @IsArray() @IsNumber({}, { each: true }) public productIds: number[]; // 替换原products字段,用产品ID数组 }
场景B:创建订单同时新建客户/产品
保留原DTO字段,后续代码中先保存关联实体。
2. 修改OrderService的createOrder方法
对应场景A:关联已有客户和产品
// 先注入CustomerRepository和ProductRepository constructor( @InjectRepository(Order) private orderRepository: Repository<Order>, @InjectRepository(Customer) private customerRepository: Repository<Customer>, @InjectRepository(Product) private productRepository: Repository<Product>, ) {} async createOrder(orderDto: CreateOrderDto) { // 1. 查询已存在的客户 const customer = await this.customerRepository.findOneBy({ id: orderDto.customerId, }); if (!customer) { throw new Error('指定的客户不存在'); } // 2. 查询已存在的产品列表 const products = await this.productRepository.findByIds(orderDto.productIds); if (products.length !== orderDto.productIds.length) { throw new Error('部分指定产品不存在'); } // 3. 创建并保存订单 const newOrder = this.orderRepository.create({ ...orderDto, customer, products, }); await this.orderRepository.save(newOrder); return newOrder; }
对应场景B:创建订单同时新建客户和产品
constructor( @InjectRepository(Order) private orderRepository: Repository<Order>, @InjectRepository(Customer) private customerRepository: Repository<Customer>, @InjectRepository(Product) private productRepository: Repository<Product>, ) {} async createOrder(orderDto: CreateOrderDto) { // 1. 先保存新建的客户 const customer = this.customerRepository.create(orderDto.customer); await this.customerRepository.save(customer); // 2. 批量保存新建的产品 const products = await Promise.all( orderDto.products.map(productData => { const product = this.productRepository.create(productData); return this.productRepository.save(product); }) ); // 3. 创建并保存订单,关联已保存的客户和产品 const newOrder = this.orderRepository.create({ ...orderDto, customer, products, }); await this.orderRepository.save(newOrder); return newOrder; }
3. 修正请求数据
场景A对应的请求示例
{ "description": "Customized waullet", "amount": 1500, "paymentMethod": "cashOnDelivery", "customizeName": "Faizan", "weight": "2.5g", "customerId": 1, // 替换为实际存在的客户ID "productIds": [10, 11] // 替换为实际存在的产品ID数组 }
场景B对应的请求示例
保留原请求结构,但删除多余的quantity字段(DTO中未定义,会被自动忽略)。
4. 检查实体关联配置
确保Order实体的关联字段配置正确:
// order.entity.ts import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, ManyToMany, JoinTable } from 'typeorm'; import { Customer } from './customer.entity'; import { Product } from './product.entity'; @Entity() export class Order { @PrimaryGeneratedColumn() id: number; // 其他业务字段... @ManyToOne(() => Customer, customer => customer.orders) customer: Customer; @ManyToMany(() => Product) @JoinTable() // 多对多关联必须添加该装饰器 products: Product[]; }
内容的提问来源于stack exchange,提问作者Fahad Subzwari
相关产品推荐
相关产品推荐

