Гид по технологиям

TypeORM в NestJS — практическое руководство

8 min read Backend Обновлено 28 Mar 2026
TypeORM в NestJS — практическое руководство
TypeORM в NestJS — практическое руководство

Гнездо птицы в кроне дерева

О чём эта статья

В этой статье подробно описано, как подключить и использовать TypeORM в проекте на NestJS. Вы найдёте пошаговые инструкции по установке, созданию сущностей, подключению к базе данных (пример на SQLite), работе с репозиториями, внедрению зависимостей, а также рекомендации по безопасности, тестированию и переходу в продакшен.

Important: краткие определения

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

Почему это важно

TypeORM позволяет писать запросы к БД в привычном объектно-ориентированном стиле. В NestJS это значит меньше шаблонного SQL-кода и более строгая типизация, если вы используете TypeScript.


Установка зависимостей

Перед началом создайте проект NestJS или откройте существующий. Для примера используем sqlite как лёгкий драйвер без настроек сервера.

Запустите установку TypeORM и интеграционного пакета NestJS:

npm install @nestjs/typeorm typeorm  

Установите драйвер SQLite:

npm install sqlite3  

Примечание: для других баз (Postgres, MySQL, MariaDB) меняется только драйвер (pg, mysql2 и т.д.) и значение type в конфигурации.

Шаг 1 — Создание сущности (Entity)

Сущность описывает структуру таблицы в коде. TypeORM использует декораторы для указания колонок и ключей.

Порядок действий:

  1. Создайте файл по соглашению NestJS: .entity.ts.
  2. Импортируйте декораторы Entity, Column, PrimaryGeneratedColumn из typeorm.
  3. Экспортируйте класс и добавьте поля (id, name и пр.).
  4. Пометьте класс декоратором @Entity().
  5. Пометьте первичный ключ декоратором @PrimaryGeneratedColumn().
  6. Остальные поля пометьте декоратором @Column().

Пример:

// src/test/test.entity.ts  
import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';  
  
@Entity()  
export class Test {  
  @PrimaryGeneratedColumn()  
  id: number;  
  
  @Column()  
  property_1: string;  
  
  @Column()  
  property_2: string;  
  
  @Column()  
  property_3: string;  
}  

Эта сущность создаст таблицу с колонками:

таблица: test
idint(11)PRIMARY KEY AUTO_INCREMENT
property_1varchar(255)
property_2varchar(255)
property_3varchar(255)

TypeORM имеет множество опций у Column (nullable, unique, length, default и др.). Ознакомьтесь с документацией по колонкам при необходимости.

Шаг 2 — Подключение приложения к базе данных

В корневом модуле приложения (обычно src/app.module.ts) нужно импортировать TypeOrmModule и передать ему конфигурацию через forRoot. Это создаст глобальное подключение, доступное во всех модулях.

Рекомендуемая минимальная конфигурация для разработки (SQLite):

// src/app.module.ts  
import { Module } from '@nestjs/common';  
import { TypeOrmModule } from '@nestjs/typeorm';  
import { Test } from './test/test.entity';  
import { Entity2 } from './entity/entity.entity';  
import { TestModule } from './test/test.module';  
  
@Module({  
  imports: [  
    TypeOrmModule.forRoot({  
      type: 'sqlite',  
      database: 'test.db',  
      entities: [Test, Entity2],  
      synchronize: true, // development only  
    }),  
    TestModule,  
  ],  
  controllers: [],  
  providers: [],  
})  
  
export class AppModule {}  

Ключевые параметры конфигурации:

  • type: имя драйвера (‘sqlite’, ‘postgres’, ‘mysql’ и т.д.).
  • database: путь/имя базы (для SQLite) или настройки хоста/порта/пользователя.
  • entities: массив классов сущностей или glob-паттерн.
  • synchronize: автоматически синхронизирует схему при запуске (только для разработки).

Важно: в продакшене не используйте synchronize: true, чтобы не потерять данные. Вместо этого используйте миграции.

Шаг 3 — Создание репозитория

Репозиторий — это слой доступа к данным. TypeORM автоматически создаёт репозиторий для каждой сущности после регистрации через forFeature в модуле.

Пример модуля сущности:

// src/test/test.module.ts  
import { Module } from '@nestjs/common';  
import { TypeOrmModule } from '@nestjs/typeorm';  
import { TestController } from './test.controller';  
import { TestService } from './test.service';  
import { Test } from './test.entity';  
  
@Module({  
  imports: [TypeOrmModule.forFeature([Test])],  
  providers: [TestService],  
  controllers: [TestController],  
})  

forFeature регистрирует репозитории для указанных сущностей в текущем модуле.

Шаг 4 — Внедрение репозитория в сервис через Dependency Injection

В NestJS репозиторий внедряется в сервис с помощью декоратора InjectRepository и типа Repository из TypeORM.

Пример сервиса:

// test.service.ts  
  
import { Injectable } from '@nestjs/common';  
import { Repository } from 'typeorm';  
import { InjectRepository } from '@nestjs/typeorm';  
import { Test } from './test.entity';  
  
@Injectable()  
export class TestService {  
  constructor(  
    @InjectRepository(Test)  
    private repo: Repository,  
  ) {}  
}  

Теперь в методах TestService вы можете вызывать стандартные методы репозитория: find, findOne, save, remove, delete, update и т.д.

Выполнение запросов: методы репозитория и QueryBuilder

TypeORM предлагает простые методы репозитория для обычных CRUD операций и мощный QueryBuilder для сложных запросов и джойнов.

Примеры:

  • repo.find({ where: { property_1: ‘value’ } })
  • repo.findOne(id)
  • repo.save(entity)
  • repo.delete(id)

QueryBuilder пример:

const users = await repo.createQueryBuilder('t')
  .where('t.property_1 = :val', { val: 'value' })
  .orderBy('t.id', 'DESC')
  .getMany();

QueryBuilder полезен для динамических условий, сложных джойнов и пагинации.

Миграции и продакшен

В разработке удобно использовать synchronize: true. Однако для продакшен-среды используйте миграции:

  1. Отключите synchronize.
  2. Генерируйте миграции при изменении сущностей.
  3. Применяйте миграции в CI/CD или вручную на сервере.

TypeORM поддерживает команды CLI для создания и запуска миграций. Миграции дают контроль над изменениями схемы и минимизируют риск потери данных.

Безопасность и конфиденциальность

  • Никогда не включайте synchronize: true в продакшен.
  • Храните секреты подключения (пароли, хосты) в переменных окружения или в секретном хранилище (Vault, AWS Secrets Manager и т.д.).
  • Для SQLite локальные файлы удобны для dev/test, но в продакшене используйте серверную СУБД (Postgres, MySQL).
  • Ограничьте права доступа БД: приложение должно иметь только необходимые привилегии.
  • Регулярно делайте бэкапы и проверяйте восстановление.

Тестирование

При модульном тестировании сервисов используйте заглушки (mocks) для репозиториев:

  • Замокайте методы репозитория (find, save и т.д.).
  • Для e2e тестов используйте отдельную тестовую базу или in-memory решение.

Пример теста с мок-репозиторием (псевдокод):

const mockRepo = { find: jest.fn().mockResolvedValue([]), save: jest.fn() };
const module = await Test.createTestingModule({
  providers: [
    TestService,
    { provide: getRepositoryToken(Test), useValue: mockRepo },
  ],
}).compile();

Когда TypeORM не лучший выбор (контрпример)

  • Проекты с исключительно сложными аналитическими запросами, где выгоднее писать оптимизированный SQL вручную.
  • Микросервисы, где нужно очень лёгкое и быстрое хранилище без ORM-слоя (например, key-value store).
  • Сценарии с высокими требованиями к масштабированию и кастомным SQL, где ORM генерирует неоптимальный код.

В таких случаях рассмотрите альтернативы: Prisma (типобезопасный генератор запросов), Sequelize, Knex (query builder) или чистый SQL.

Альтернативы и сравнительная таблица

ИнструментПодходит дляПлюсыМинусы
TypeORMТрадиционные приложения NestJS с TypeScriptДекораторы, интеграция с NestJS, репозитории, QueryBuilderПоддержка миграций требует внимания, иногда тонкие баги в генерации SQL
PrismaПроекты с высокой типобезопасностьюСильная типизация, удобный клиентНе использует декораторы, миграции и подход отличаются
SequelizeJS/TS, зрелая ORMШироко используется, много драйверовAPI менее «typescript-ориентирован»
KnexQuery builderПолный контроль SQLСам по себе не ORM — нужен слой моделей

Ментальные модели и эвристики

  • Сущность = таблица, экземпляр = строка.
  • Репозиторий = набор CRUD-операций над сущностью.
  • synchronize: true = удобно, но опасно.
  • Используйте QueryBuilder, когда стандартных методов недостаточно.

Роль‑ориентированные чеклисты

Разработчик:

  • Создал Entity с нужными колонками.
  • Протестировал репозиторий методом save/find.
  • Не включил synchronize в production конфиг.

DevOps:

  • Хранит секреты подключения в безопасном месте.
  • Автоматизировал миграции в CI/CD.
  • Настроил бэкапы и мониторинг БД.

QA:

  • Проверил CRUD-операции и граничные условия.
  • Выполнил тесты с реальными размерами данных.
  • Проверил поведение при ошибках доступа к базе.

Критерии приёмки

  • API-сервис корректно сохраняет и читает данные из БД.
  • Миграции корректно применяются к тестовой/стейдж-среде.
  • Производительность запросов соответствует SLA (если применимо).
  • В продакшене synchronize выключен и используется только миграция.

Примеры сценариев и тесты приёмки

Тест-случай: создание нового Test

  • Шаги: вызвать endpoint POST /tests с телом { property_1, property_2, property_3 }
  • Ожидание: статус 201 и запись появляется в БД (repo.findOne возвращает запись)

Тест-случай: обновление записи

  • Шаги: PATCH /tests/:id с изменёнными полями
  • Ожидание: ответ 200 и значения изменены в БД

Руководство по миграциям — мини-методология

  1. В ветке фичи измените сущности.
  2. Сгенерируйте миграцию (CLI команды TypeORM или ручной скрипт).
  3. Просмотрите SQL миграции вручную.
  4. Создайте PR с миграцией.
  5. На этапе CI примените миграцию к тестовой БД и запустите тесты.
  6. Примените миграцию на staging, затем на production.

Отладка и типичные ошибки

  • Проблема: сущности не обнаруживаются. Причина: entities не указаны в конфиге или путь/импорт неверны.
  • Проблема: миграции не применяются. Причина: synchronize выключен и миграции не запускались вручную.
  • Проблема: несоответствие типов/тайпстринги. Причина: несовпадение полей в сущности и в БД — проверьте миграции.

Decision flow — как выбрать TypeORM?

flowchart TD
  A[Начать проект на NestJS] --> B{Планируется работать с SQL?}
  B -- Да --> C{Нужна ли tight TypeScript-типизация клиентского API?}
  C -- Да --> D[Рассмотреть Prisma]
  C -- Нет --> E[TypeORM — хорошая опция]
  B -- Нет --> F[Рассмотреть NoSQL/другие хранилища]

Лучшие практики

  • Разделяйте слои: контроллеры не должны содержать SQL.
  • Используйте DTO и валидацию (class-validator) для входных данных.
  • Пишите интеграционные тесты с реальной БД в CI.
  • Логируйте ошибки доступа к БД и время выполнения тяжёлых запросов.

Notes: локальные альтернативы для России

  • Для разработки часто используют SQLite или локальные контейнеры Postgres.
  • При деплое в облако предпочтительнее управляемые Postgres/Cloud SQL решения.

Краткая галерея крайних случаев

  • Edge-case: большой объём массовой вставки — репозиторий.save может быть медленен; используйте queryRunner и BULK INSERT.
  • Edge-case: сложные агрегаты и аналитика — лучше выполнять на стороне БД через оптимизированный SQL.

Короткое объявление для команды (100–200 слов)

TypeORM интегрируется с NestJS и позволяет быстро перейти от сущностей к рабочей базе данных. Для локальной разработки удобно использовать SQLite и synchronize: true, но в продакшене используйте миграции и управляемую СУБД. В ближайшем спринте создайте сущности, настройте миграции и добавьте CI шаг для их применения на тестовом окружении.


Итог

TypeORM — надёжный инструмент для большинства приложений на NestJS. Он ускоряет разработку, обеспечивает связность модели и базы данных и интегрируется с инфраструктурой NestJS. Помните про запрет использования synchronize в production и продуманную стратегию миграций.

Summary:

  • Настройте TypeOrmModule.forRoot в AppModule и используйте forFeature в модулях.
  • Создавайте сущности с декораторами Entity/Column/PrimaryGeneratedColumn.
  • Внедряйте репозитории с InjectRepository и используйте методы репозитория или QueryBuilder.
  • Для продакшена используйте миграции, секреты в переменных окружения и бэкапы.
Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

Nearby Sharing в Windows 10: быстрый обмен файлами
Windows

Nearby Sharing в Windows 10: быстрый обмен файлами

Медиа‑источник не отображается в OBS — как исправить
OBS

Медиа‑источник не отображается в OBS — как исправить

Поменять папку для скриншотов в One UI 5.1
Mobile

Поменять папку для скриншотов в One UI 5.1

Собрать мощный дешёвый ПК из серверных комплектующих
Сборка ПК

Собрать мощный дешёвый ПК из серверных комплектующих

BitTorrent на Android: как скачивать и делиться
Android.

BitTorrent на Android: как скачивать и делиться

Отключить Windows Defender в Windows 10
Windows

Отключить Windows Defender в Windows 10