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

使用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 04:15:36