我是 NestJS 的新手,想知道当 DTO 的属性与实体属性不 1:1 匹配时,将 DTO 转换为实体的最佳实践是什么。
例如,我有以下实体定义:
@Entity()
export class Category {
@PrimaryGeneratedColumn()
id: number
@Column()
name: string
@OneToMany(() => questionToCategory, questionToCategory => questionToCategory.category)
public questionToCategories: QuestionToCategory[];
}
export class Question {
@PrimaryGeneratedColumn()
id: number
@Column()
title: string
@Column()
text: string
@OneToMany(() => QuestionToCategory, questionToCategory => questionToCategory.question)
public questionToCategories: QuestionToCategory[];
}
export class QuestionToCategory {
@PrimaryGeneratedColumn()
public questionToCategoryId: number
@Column()
public questionId: number
@Column()
public categoryId: number
@Column()
public order: number
@ManyToOne(() => Question, (question) => question.questionToCategories)
public question: Question
@ManyToOne(() => Category, (category) => category.questionToCategories)
public category: Category
}
通过这些实体定义,问题和类别之间存在多对多关系
要保存问题实体中的多对多关系,您可以执行以下操作:
questionToCategories: { categoryId: "some_id_value" }
这工作正常,但是我的 DTO 结构与此结构不完美匹配。
如果我的问题 dto 类似于以下内容:
export class CreateQuestionDto {
@IsString()
title?: string;
@IsString()
title?: string;
@IsOptional()
@IsArray()
bundles: string[];
}
其中bundles是与类别对应的id数组。我无法直接将此 DTO 保存为实体,因为包字段与 QuestionToCategories 不匹配。在 NestJS 中,是否有任何最佳实践可以将 dto 转换为实体的等效表示
我假设您的 DTO 无法根据实体进行更改和匹配。 在这种情况下,您无法通过铸造直接保存,并且无法执行级联插入。您可以做的是:创建一个映射器服务,该服务最初将保存问题,获取其 ID,然后根据您的 QuestionToCategory 实体映射它,然后保存:
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { CreateQuestionDto } from './dto/create-question.dto';
import { Question } from './entities/question.entity';
import { Category } from './entities/category.entity';
import { QuestionToCategory } from './entities/question-to-category.entity';
@Injectable()
export class QuestionService {
constructor(
@InjectRepository(Question)
private questionRepository: Repository<Question>,
@InjectRepository(Category)
private categoryRepository: Repository<Category>,
@InjectRepository(QuestionToCategory)
private questionToCategoryRepository: Repository<QuestionToCategory>,
) {}
async create(createQuestionDto: CreateQuestionDto): Promise<Question> {
const { title, text, bundles } = createQuestionDto;
const question = new Question();
question.title = title;
question.text = text;
const savedQuestion = await this.questionRepository.save(question);
const questionToCategories: QuestionToCategory[] = [];
for (const categoryId of bundles) {
const category = await this.categoryRepository.findOne(categoryId);
if (category) {
const questionToCategory = new QuestionToCategory();
questionToCategory.question = savedQuestion;
questionToCategory.category = category;
questionToCategories.push(questionToCategory);
}
}
await this.questionToCategoryRepository.save(questionToCategories);
return this.questionRepository.findOne(savedQuestion.id, { relations: ['questionToCategories'] });
}
}
在服务类中,您可以注入实体的存储库并使用它们相应地获取和保存在表中