Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Сущности и репозитории

Сущность (entity) — класс, который описывает таблицу: каждое свойство с декоратором становится столбцом, а каждый объект — строкой. Репозиторий — готовый объект TypeORM с методами для одной таблицы: найти, сохранить, удалить. Вместо массива из второй главы сервис статей будет работать с репозиторием.

Сущность статьи

Класс Post уже лежит в src/posts/entities/post.entity.ts. Добавьте ему декораторы TypeORM:

// src/posts/entities/post.entity.ts
import { Column, CreateDateColumn, Entity, PrimaryGeneratedColumn } from 'typeorm';
 
@Entity()
export class Post {
  @PrimaryGeneratedColumn()
  id: number;
 
  @Column({ length: 120 })
  title: string;
 
  @Column('text')
  content: string;
 
  @CreateDateColumn()
  createdAt: Date;
}
ДекораторЧто создаёт
@Entity()Таблицу post
@PrimaryGeneratedColumn()Первичный ключ, который база увеличивает сама
@Column()Обычный столбец; тип берётся из TypeScript
@Column('text')Столбец с явно указанным типом
@CreateDateColumn()Дату создания, заполняется автоматически

Регистрация в модуле

Модуль статей сообщает TypeORM о своей сущности:

// src/posts/posts.module.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Post } from './entities/post.entity';
import { PostsController } from './posts.controller';
import { PostsService } from './posts.service';
 
@Module({
  imports: [TypeOrmModule.forFeature([Post])],
  controllers: [PostsController],
  providers: [PostsService],
})
export class PostsModule {}

После сохранения сервер перезапустится, и благодаря synchronize: true в файле blog.sqlite появится таблица post со столбцами id, title, content и createdAt.

Репозиторий в сервисе

forFeature() создаёт репозиторий, а декоратор @InjectRepository() внедряет его в сервис:

// src/posts/posts.service.ts
import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { CreatePostDto } from './dto/create-post.dto';
import { Post } from './entities/post.entity';
 
@Injectable()
export class PostsService {
  constructor(
    @InjectRepository(Post)
    private readonly postsRepository: Repository<Post>,
  ) {}
 
  findAll(): Promise<Post[]> {
    return this.postsRepository.find({ order: { createdAt: 'DESC' } });
  }
 
  async findOne(id: number): Promise<Post> {
    const post = await this.postsRepository.findOneBy({ id });
    if (!post) {
      throw new NotFoundException(`Статья ${id} не найдена`);
    }
    return post;
  }
 
  create(dto: CreatePostDto): Promise<Post> {
    const post = this.postsRepository.create(dto);
    return this.postsRepository.save(post);
  }
}

Все методы репозитория асинхронные и возвращают промисы. Контроллер менять не нужно: NestJS сам дождётся промиса. Создайте статью POST-запросом, перезапустите сервер и откройте /posts — статья осталась на месте.

Основные методы репозитория

МетодЧто делает
find(options)Список строк с условиями, сортировкой, ограничением
findOneBy({ id })Одна строка или null
create(data)Новый объект сущности, ещё не сохранённый
save(entity)Вставляет новую строку или обновляет существующую
update(id, data)Меняет поля без загрузки объекта
delete(id)Удаляет строку по ключу
count(options)Количество строк

Частая ошибка

Ошибка Nest can't resolve dependencies of the PostsService (?) с упоминанием PostRepository значит, что в модуле забыли TypeOrmModule.forFeature([Post]). Репозиторий существует только в модулях, которые зарегистрировали сущность. Если репозиторий нужен другому модулю, добавьте forFeature() и туда либо экспортируйте сервис, который с ним работает.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.