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

TypeORM中1:N关联下advertiserId无法插入关联列的问题排查

解决TypeORM中关联字段advertiserId无法插入的问题

问题描述

已配置Advertiser与AdvertisementRequest表的1:N关联实体,但无法将advertiserId插入到advertisement-request表的advertiserId列。在服务层代码中执行advertisementRequest.advertiserId = decodeJwt.advertiserId赋值后保存,该字段仍为undefined或null。

AdvertisementRequest 实体

import { Exclude } from 'class-transformer';
import {Column ,CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn, ManyToOne, RelationId} from 'typeorm';
import {Advertiser} from "./advertiser.entity";

@Entity('advertisement_request')
export class AdvertisementRequest {
    @PrimaryGeneratedColumn()
    id: number;    
@Column()
    companyName: string;    
@Column()
    companyRegisterNumber: string;    
@Column()
    productName: string;    
@Column()
    creatorSubscriberRangeId: number;    
@Column()
    creatorHeadcount: number;    
@CreateDateColumn({
        type: 'timestamp', default: () => 'CURRENT_TIMESTAMP(6)'})
        createdAt: Date;    
@UpdateDateColumn({
        type: 'timestamp', 
default: () => 'CURRENT_TIMESTAMP(6)',
onUpdate: 'CURRENT_TIMESTAMP(6)'})
updatedAt: Date;    

@ManyToOne(() => Advertiser)
advertiser: Advertiser
    @RelationId((advertisementRequest : AdvertisementRequest) => advertisementRequest.advertiser)
    advertiserId: number;}

Advertiser 实体

import { Exclude } from 'class-transformer';
import {
  Column,
  CreateDateColumn,
  Entity,
  PrimaryGeneratedColumn,
  UpdateDateColumn,
    OneToMany
} from 'typeorm';
import {AdvertisementRequest} from "./advertisement-request.entity";

@Entity('advertiser')
export class Advertiser {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  name: string;

  @Column()
  email: string;

  @Exclude()
  @Column({ type: 'varchar', length: 255 })
  password: string;

  @CreateDateColumn({
    type: 'timestamp',
  default: () => 'CURRENT_TIMESTAMP(6)'
  })
  createdAt: Date;

  @UpdateDateColumn({
    type: 'timestamp',
    default: () => 'CURRENT_TIMESTAMP(6)',
    onUpdate: 'CURRENT_TIMESTAMP(6)'
  })
  updatedAt: Date;

  @OneToMany(() => AdvertisementRequest, advertisementRequest => advertisementRequest.advertiser)
  advertisementRequests: AdvertisementRequest[];
}

AdvertisementRequestService 代码

import { Injectable } from '@nestjs/common';
import { AdvertiseRequestDto } from "./dto/advertise-request.dto";
import { AdvertisementRequest } from "../common/entities/advertisement-request.entity";
import { AdvertisementRequestRepository } from "./advertisement-request.repository";
import { AdvertiserRepository } from "../advertiser/advertiser.repository";


@Injectable()
export class AdvertisementRequestService {
    constructor(
        private readonly AdvertisementRequestRepository: AdvertisementRequestRepository,
        private readonly advertiserRepository: AdvertiserRepository
    ) {}

    async advertiseRequest(
        advertisementData: AdvertiseRequestDto,
        decodeJwt: any
        ): Promise<AdvertisementRequest>{
      const { companyName, companyRegisterNumber, productName, creatorSubscriberRangeId, creatorHeadcount } = advertisementData;
      const advertisementRequest = new AdvertisementRequest();

        advertisementRequest.companyName = companyName;
        advertisementRequest.companyRegisterNumber = companyRegisterNumber;
        advertisementRequest.productName = productName;
        advertisementRequest.creatorSubscriberRangeId = creatorSubscriberRangeId;
        advertisementRequest.creatorHeadcount = creatorHeadcount;
        advertisementRequest.advertiserId = decodeJwt.advertiserId; // 无法插入到数据库列

        const saveAdvertisementRequest = await this.AdvertisementRequestRepository.save(advertisementRequest);
          return saveAdvertisementRequest;
    }

}

解决方案

问题根源在于:TypeORM的@RelationId装饰器生成的是只读字段,它仅用于从关联的advertiser实体中自动提取ID,无法通过直接赋值的方式将其持久化到数据库。以下两种方法可以解决这个问题:

方法一:关联Advertiser实体对象

通过查询获取对应的Advertiser实例,将实例赋值给advertisementRequest的advertiser属性,TypeORM会自动处理外键字段的插入:

修改服务层代码:

async advertiseRequest(
    advertisementData: AdvertiseRequestDto,
    decodeJwt: any
): Promise<AdvertisementRequest>{
  const { companyName, companyRegisterNumber, productName, creatorSubscriberRangeId, creatorHeadcount } = advertisementData;
  
  // 根据ID查询对应的Advertiser实体
  const advertiser = await this.advertiserRepository.findOneBy({ id: decodeJwt.advertiserId });
  // 可选:如果找不到广告主,抛出异常
  if (!advertiser) {
    throw new NotFoundException('广告主不存在');
  }

  const advertisementRequest = new AdvertisementRequest();
  advertisementRequest.companyName = companyName;
  advertisementRequest.companyRegisterNumber = companyRegisterNumber;
  advertisementRequest.productName = productName;
  advertisementRequest.creatorSubscriberRangeId = creatorSubscriberRangeId;
  advertisementRequest.creatorHeadcount = creatorHeadcount;
  // 关联实体对象,替代直接赋值advertiserId
  advertisementRequest.advertiser = advertiser;

  const saveAdvertisementRequest = await this.AdvertisementRequestRepository.save(advertisementRequest);
  return saveAdvertisementRequest;
}

方法二:手动添加独立的advertiserId列

如果不想每次都查询Advertiser实体,可以修改AdvertisementRequest实体,添加一个带@Column的独立advertiserId字段,同时保留关联关系:

修改AdvertisementRequest实体:

import { Exclude } from 'class-transformer';
import {Column ,CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn, ManyToOne, JoinColumn} from 'typeorm';
import {Advertiser} from "./advertiser.entity";

@Entity('advertisement_request')
export class AdvertisementRequest {
    @PrimaryGeneratedColumn()
    id: number;    
@Column()
    companyName: string;    
@Column()
    companyRegisterNumber: string;    
@Column()
    productName: string;    
@Column()
    creatorSubscriberRangeId: number;    
@Column()
    creatorHeadcount: number;    
@CreateDateColumn({
        type: 'timestamp', default: () => 'CURRENT_TIMESTAMP(6)'})
        createdAt: Date;    
@UpdateDateColumn({
        type: 'timestamp', 
default: () => 'CURRENT_TIMESTAMP(6)',
onUpdate: 'CURRENT_TIMESTAMP(6)'})
updatedAt: Date;    

// 手动添加外键列
@Column()
advertiserId: number;

// 配置关联关系,指定关联的列名
@ManyToOne(() => Advertiser, { nullable: false })
@JoinColumn({ name: 'advertiserId' })
advertiser: Advertiser;
}

修改后,服务层中直接赋值advertisementRequest.advertiserId = decodeJwt.advertiserId即可正常将值插入数据库,同时TypeORM仍会维护实体间的关联关系。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 23:05:41