NestJS + TypeORM: работа с базой данных

от автора

в
Время чтения: 4 мин.

TypeORM — один из самых популярных ORM (Object-Relational Mapping) для TypeScript и Node.js. В сочетании с NestJS он позволяет удобно работать с базами данных, используя декларативный подход на основе сущностей (Entities) и репозиториев (Repositories).

В этом руководстве мы разберём:

  1. Настройку TypeORM в NestJS.
  2. Создание сущностей (Entities) и репозиториев (Repositories).
  3. CRUD-операции (Create, Read, Update, Delete).
  4. Связи между таблицами (One-to-One, Many-to-One, Many-to-Many).
  5. Миграции базы данных.

1. Установка и настройка TypeORM

Установка необходимых пакетов

npm install @nestjs/typeorm typeorm pg  # PostgreSQL (или mysql2, sqlite3 и т. д.)

Подключение к базе данных

Добавим конфигурацию в app.module.ts:

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';

@Module({
  imports: [
    TypeOrmModule.forRoot({
      type: 'postgres',  // Тип БД (mysql, sqlite, mssql и др.)
      host: 'localhost',
      port: 5432,
      username: 'postgres',
      password: 'password',
      database: 'nestjs_db',
      entities: [__dirname + '/**/*.entity{.ts,.js}'],  // Где искать сущности
      synchronize: true,  // Автоматическое обновление схемы (только для разработки!)
    }),
  ],
})
export class AppModule {}

⚠️ Важно!

  • synchronize: true автоматически обновляет схему БД, но не подходит для продакшена (используйте миграции).
  • Для разных СУБД (postgres, mysql, sqlite) настройки могут отличаться.

2. Создание сущности (Entity)

Сущность (Entity) — это класс, который описывает структуру таблицы в БД.

Пример: Сущность User

Создадим user.entity.ts:

import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';

@Entity()  // Декоратор указывает, что это сущность БД
export class User {
  @PrimaryGeneratedColumn()  // Автоинкрементный ID
  id: number;

  @Column()  // Поле таблицы
  name: string;

  @Column({ unique: true })  // Уникальное поле
  email: string;

  @Column({ nullable: true })  // Необязательное поле
  age?: number;
}

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

Добавим TypeOrmModule.forFeature([User]) в users.module.ts:

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { User } from './user.entity';
import { UsersService } from './users.service';
import { UsersController } from './users.controller';

@Module({
  imports: [TypeOrmModule.forFeature([User])],  // Регистрация репозитория
  providers: [UsersService],
  controllers: [UsersController],
})
export class UsersModule {}

Теперь UsersService может внедрить Repository<User>:

import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { User } from './user.entity';

@Injectable()
export class UsersService {
  constructor(
    @InjectRepository(User)  // Внедрение репозитория
    private usersRepository: Repository<User>,
  ) {}

  async findAll(): Promise<User[]> {
    return this.usersRepository.find();
  }

  async create(user: Partial<User>): Promise<User> {
    return this.usersRepository.save(user);
  }
}

3. CRUD-операции

Добавление методов в UsersController

import { Controller, Get, Post, Body, Param } from '@nestjs/common';
import { UsersService } from './users.service';
import { User } from './user.entity';

@Controller('users')
export class UsersController {
  constructor(private usersService: UsersService) {}

  @Get()
  async findAll(): Promise<User[]> {
    return this.usersService.findAll();
  }

  @Post()
  async create(@Body() user: User): Promise<User> {
    return this.usersService.create(user);
  }

  @Get(':id')
  async findOne(@Param('id') id: number): Promise<User> {
    return this.usersService.findOne(id);
  }
}

Основные методы TypeORM

МетодОписаниеПример SQL
repository.find()Получить все записиSELECT * FROM users
repository.findOne(id)Найти по IDSELECT * FROM users WHERE id = ?
repository.save(entity)Сохранить или обновить записьINSERT INTO users ...
repository.delete(id)Удалить записьDELETE FROM users WHERE id = ?
repository.update(id, data)Обновить записьUPDATE users SET ... WHERE id = ?

4. Связи между таблицами

One-to-Many (Пользователь → Посты)

// user.entity.ts
import { Entity, OneToMany } from 'typeorm';
import { Post } from './post.entity';

@Entity()
export class User {
  @OneToMany(() => Post, (post) => post.author)  // 1 пользователь → N постов
  posts: Post[];
}
// post.entity.ts
import { Entity, ManyToOne } from 'typeorm';
import { User } from './user.entity';

@Entity()
export class Post {
  @ManyToOne(() => User, (user) => user.posts)  // N постов → 1 пользователь
  author: User;
}

Many-to-Many (Посты ↔ Теги)

// post.entity.ts
import { Entity, ManyToMany, JoinTable } from 'typeorm';
import { Tag } from './tag.entity';

@Entity()
export class Post {
  @ManyToMany(() => Tag)
  @JoinTable()  // Создаёт промежуточную таблицу
  tags: Tag[];
}
// tag.entity.ts
import { Entity } from 'typeorm';

@Entity()
export class Tag {
  name: string;
}

5. Миграции (Migrations)

Миграции помогают безопасно изменять схему БД.

Настройка TypeORM CLI

Создайте ormconfig.json:

{
  "type": "postgres",
  "host": "localhost",
  "port": 5432,
  "username": "postgres",
  "password": "password",
  "database": "nestjs_db",
  "entities": ["src/**/*.entity{.ts,.js}"],
  "migrations": ["migrations/*{.ts,.js}"],
  "cli": { "migrationsDir": "migrations" }
}

Создание и применение миграции

npx typeorm migration:create -n CreateUserTable  # Создаёт файл миграции
npx typeorm migration:run                       # Применяет миграции
npx typeorm migration:revert                    # Откатывает последнюю миграцию

Заключение

  • TypeORM + NestJS = мощный инструмент для работы с БД.
  • Сущности (Entities) описывают структуру таблиц.
  • Репозитории (Repositories) дают удобные методы для CRUD.
  • Связи (@OneToMany, @ManyToMany) упрощают работу с данными.
  • Миграции помогают безопасно обновлять схему БД.

Что дальше?

  • Добавить валидацию данных (class-validator).
  • Оптимизировать запросы с ленивой загрузкой ({ lazy: true }).
  • Использовать Docker для развёртывания PostgreSQL.

Документация:

Попробуйте создать своё приложение с этими инструментами! 🚀


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Сколько будет 4 + 4?