如何配置DTO适配TypeORM关联:项目与类型关联问题(PostgreSQL)
解决方案
1. 修正实体关联配置
首先要把搞反的关联关系纠正过来,匹配你的业务逻辑:一个Project对应一个ProjectType,一个ProjectType对应多个Project。
Project 实体(修正后)
import { Column, CreateDateColumn, Entity, ManyToOne, PrimaryGeneratedColumn, UpdateDateColumn, JoinColumn, } from 'typeorm'; import { ProjectType } from '../project-type/entities/project-type.entity'; @Entity('projects') export class Project { @PrimaryGeneratedColumn() id: number; @Column() name: string; // 一个Project对应一个ProjectType,使用ManyToOne关联 @ManyToOne(() => ProjectType, (projectType) => projectType.projects) @JoinColumn({ name: 'project_type_id' }) // 指定数据库外键列名,可选,默认会生成`projectTypeId` type: ProjectType; }
ProjectType 实体(修正后)
import { Project } from '@/projects/entities/project.entity'; import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from 'typeorm'; @Entity('project_type') export class ProjectType { @PrimaryGeneratedColumn() id: number; @Column() name: string; // 一个ProjectType对应多个Project,使用OneToMany关联 @OneToMany(() => Project, (project) => project.type) projects: Project[]; }
2. 调整CreateProjectDto适配前端传参
前端只传ProjectType的id,所以DTO里要改成接收数字类型的typeId,而非字符串或完整对象:
import { ApiProperty } from '@nestjs/swagger'; import { IsNotEmpty, IsNumber, IsOptional, IsString } from 'class-validator'; export class CreateProjectDto { @ApiProperty({ description: 'project name', example: 'ToDo' }) @IsNotEmpty() @IsString() readonly name: string; @ApiProperty({ description: 'project type id', example: 1 }) @IsOptional() @IsNumber() readonly typeId: number; // 改为接收类型id,数字格式 }
3. 服务层处理关联逻辑
在ProjectService的create方法里,把前端传的typeId转换成实体关联对象:
import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { Project } from './entities/project.entity'; import { CreateProjectDto } from './dto/create-project.dto'; import { ProjectType } from '../project-type/entities/project-type.entity'; @Injectable() export class ProjectService { constructor( @InjectRepository(Project) private projectRepo: Repository<Project>, @InjectRepository(ProjectType) private projectTypeRepo: Repository<ProjectType>, ) {} async create(createProjectDto: CreateProjectDto) { const { name, typeId } = createProjectDto; let projectType: ProjectType | undefined; if (typeId) { // 方式1:查询验证类型是否存在(推荐,避免无效id) projectType = await this.projectTypeRepo.findOneBy({ id: typeId }); // 方式2:直接用id关联(无需查询,适合信任前端传参的场景) // projectType = { id: typeId } as ProjectType; } const project = this.projectRepo.create({ name, type: projectType, }); return this.projectRepo.save(project); } }
错误原因说明
- 最初的实体关联完全搞反:Project用了
OneToMany、ProjectType用了ManyToOne,和你的业务逻辑冲突,导致TypeORM类型推导报错。 - 后来把DTO的
type改成ProjectType类型后,虽然类型报错消失,但前端仅传id无法构造完整的ProjectType对象,因此保存失败。
内容的提问来源于stack exchange,提问作者Cesar Gomez
相关产品推荐
相关产品推荐

