努力使用 NestJS/TypeORM 在 OneToMany/ManyToOne 关系中保存实体



书店练习。可以为Book分配单个Genre尝试使用 DTO 中提供的genreId分配新书。

图书存储库

@EntityRepository(Book)
export class BookRepository extends Repository<Book> {
constructor(
private genreService: GenresService,
) {
super();
}
async createBook(createBookDto: CreateBookDto): Promise<Book> {
const genre = await this.genreService.getOne(createBookDto.genreId);
const newBook = this.create({
...createBookDto,
genre,
});
return newBook.save();
}
}

流派服务

@Injectable()
export class GenresService {
constructor(
@InjectRepository(GenreRepository) private readonly genreRepository: GenreRepository,
) {}
async getOne(id: number): Promise<Genre> {
return this.getById(id);
}
private async getById(id: number): Promise<Genre> {
const found = await this.genreRepository.findOne(id);
if (!found) {
throw new NotFoundException(`Genre with id ${id} not found.`);
}
return found;
}
}

BookRepository 和 GenreRepository 由BookstoreModule一起导入,如下所示:

imports: [
TypeOrmModule.forFeature([
GenreRepository,
BookRepository,
AuthorRepository,
]),
// ...etc
},

NestJS吐出以下错误:

[ExceptionsHandler] this.genreService.getOne is not a function +1045981ms
TypeError: this.genreService.getOne is not a function
at BookRepository.createBook (/Users/artur/Code/Sandbox/books-nest/dist/bookstore/books/book.repository.js:21:47)
at BooksService.createBook (/Users/artur/Code/Sandbox/books-nest/dist/bookstore/books/books.service.js:29:36)
at BooksController.create (/Users/artur/Code/Sandbox/books-nest/dist/bookstore/books/books.controller.js:31:33)

试图注入GenreRepository into the书库'

constructor(
@InjectRepository(GenreRepository) private genreRepository: GenreRepository,
){
super();
}

.findOne()从那里开始,错误是:

No metadata for "2" was found. +26884ms
EntityMetadataNotFound: No metadata for "2" was found.

(2 是流派 ID 的 ID(

不确定我的储蓄方法是否正确。也许从BookRepository中找到流派的想法是错误的,应该以不同的方式解决。如果是这样,如何?

对我来说,createBook方法应该位于BookService中,BookService需要注入GenreService,然后genreService.getOne(createBookDto.genreId)您应该从BookService.
让服务处理数据流imo的业务逻辑/编排更有意义。

我建议尝试使用以下代码:

图书服务

@Injectable()
export class BookService {
constructor(
@InjectRepository(BookRepository) private readonly bookRepository: BookRepository, 
private genreService: GenreService // <= here you go, you inject the genreService into the bookService to take advantage of its methods
) {}
async getOne(id: number): Promise<Genre> {
return this.getById(id);
}
async createBook(createBookDto: CreateBookDto): Promise<Book> {
const genre = await this.genreService.getOne(createBookDto.genreId);
const newBook = this.create({
...createBookDto,
genre,
});
return newBook.save();
}
private async getById(id: number): Promise<Genre> {
const found = await this.bookRepository.findOne(id);
if (!found) {
throw new NotFoundException(`Book with id ${id} not found.`);
}
return found;
}
}

图书存储库

@EntityRepository(Book)
export class BookRepository extends Repository<Book> {}

流派服务

@Injectable()
export class GenresService {

constructor(
@InjectRepository(GenreRepository) private readonly genreRepository: GenreRepository,
) {}

async getOne(id: number): Promise<Genre> {
return this.getById(id);
}

private async getById(id: number): Promise<Genre> {
const found = await this.genreRepository.findOne(id);

if (!found) {
throw new NotFoundException(`Genre with id ${id} not found.`);
}

return found;
}
}

流派存储库

@EntityRepository(Genre)
export class GenreRepository extends Repository<Genre> {}

编辑 DTO 注释

CreateBookDto

import { Exclude, Expose } from 'class-transformer';
import { IsNumber, IsString, IsDate } from 'class-validator';
@Exclude()
export class CreateBookDto {
@Expose()
@IsNumber()
genreId: number;
@Expose()
@IsString()
title: string;
@Expose()
@IsString()
author: string;
@Expose()
@IsDate()
date_of_publication: Date;
// rest of informations....
}

请注意,我们将class-transformerclass-validator一起使用,以便实例化和验证正确的CreateBookDto。如果使用验证管道,则可以在控制器级别实例化 CreateBookDto

让我知道它是否有帮助:)

最新更新