书店练习。可以为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-transformer
与class-validator
一起使用,以便实例化和验证正确的CreateBookDto。如果使用验证管道,则可以在控制器级别实例化 CreateBookDto
让我知道它是否有帮助:)