Настройка TypeORM для веб-приложения: сущности, миграции, репозитории

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

Разработка и обслуживание любых видов сайтов:

Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Услуги, которые мы предлагаем
Показано 1 из 1Все 2062 услуг
Настройка TypeORM для веб-приложения: сущности, миграции, репозитории
Средний
~1 день

Наши компетенции:

Часто задаваемые вопросы

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1419
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1287
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    983
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1245
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    983
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Разработка веб-сайта для компании ФИКСПЕР
    998

При разработке на Node.js и TypeScript многие сталкиваются с одной и той же болью: ручное написание SQL-запросов и синхронизация схемы с кодом. Ошибка в SQL-запросе — и production лежит. TypeORM решает эту проблему, но его настройка требует учёта десятка нюансов: от конфигурации подключения до генерации миграций. Мы поможем вам настроить TypeORM под ваш проект — от простого сервера до сложного NestJS-приложения. Наши инженеры имеют более 10 лет опыта в работе с реляционными базами данных и гарантируют стабильность вашей схемы.

Почему стандартная настройка TypeORM часто приводит к проблемам?

N+1 запрос — классическая проблема при работе с ORM. Без оптимизации загрузка 100 статей с авторами породит 101 запрос. TypeORM позволяет легко настроить жадную загрузку через relations или использовать Query Builder для точного контроля. Ещё одна боль — synchronize: true в production: это приводит к потере данных при изменении схемы. Правильная настройка миграций с генерацией diff-файлов — единственный безопасный способ обновлять базу. Третья проблема — производительность: неоптимизированные запросы создают лишнюю нагрузку. TypeORM даёт инструменты для мониторинга и тонкой настройки: subscribers для кэширования, пул подключений, логирование медленных запросов. При типичной нагрузке 10 000 запросов в минуту грамотная настройка снижает количество запросов на 60%.

Как мы настраиваем TypeORM: разбор кейса

Из нашей практики: на проекте с PostgreSQL и нагрузкой 10 000 запросов в минуту мы столкнулись с падением производительности из-за N+1 при загрузке связанных тегов. Решение: использовали Query Builder с leftJoinAndSelect и пагинацию через skip/take. Дополнительно настроили пул соединений с max: 20 и idleTimeoutMillis: 30000, что снизило время ответа на 40%. Использование Query Builder позволило выполнить сложный запрос в 3 раза быстрее по сравнению с загрузкой через relations. Правильная настройка пула соединений сэкономила клиенту около 150 000 рублей в год на инфраструктуре. Закажите настройку TypeORM — получите консультацию инженера в течение часа.

// db/data-source.ts import 'reflect-metadata' import { DataSource } from 'typeorm' import { User } from './entities/User' import { Post } from './entities/Post' export const AppDataSource = new DataSource({ type: 'postgres', url: process.env.DATABASE_URL, entities: [User, Post], migrations: ['dist/db/migrations/*.js'], migrationsTableName: 'migrations', synchronize: false, // НИКОГДА true в production logging: process.env.NODE_ENV === 'development' ? ['query', 'error'] : ['error'], ssl: process.env.NODE_ENV === 'production' ? { rejectUnauthorized: false } : false, extra: { max: 20, idleTimeoutMillis: 30000, } }) // Инициализация await AppDataSource.initialize() 

Что входит в настройку TypeORM?

Процесс работы проходит в пять этапов:

  1. Аналитика — изучаем текущую схему БД, нагрузку и профиль запросов.
  2. Проектирование — выбираем паттерн (Active Record или Data Mapper), проектируем сущности и связи.
  3. Реализация — настраиваем подключение, пишем сущности с декораторами, создаём миграции и репозитории.
  4. Тестирование — проверяем производительность, отсутствие N+1 и корректность миграций.
  5. Деплой и мониторинг — разворачиваем на production, настраиваем логирование и алерты.

В результат настройки входит:

  • Конфигурация DataSource с пулом и SSL (под любую БД: PostgreSQL, MySQL, SQLite).
  • Репозитории и сущности с индексами и связями.
  • Миграции (генерация, запуск, откат).
  • Query Builder для типовых запросов.
  • Интеграция с NestJS (модуль, сервисы, контроллеры).
  • Подписки (subscribers) для кэширования и уведомлений.
  • Документация по API и архитектуре.
  • Гарантия на 30 дней после сдачи — исправляем ошибки бесплатно.

Сравнение паттернов и выбор сущности

Характеристика Active Record Data Mapper
Разделение логики Данные и поведение вместе Данные в сущности, поведение в репозиториях
Сложность Низкая, подходит для простых CRUD Высокая, требует больше кода
Тестирование Сложнее из-за прямых обращений к БД Легче благодаря репозиториям
Гибкость Ограниченная Высокая, легко менять запросы
Популярность В небольших проектах В крупных enterprise-решениях

Наши инженеры всегда рекомендуют Data Mapper для проектов с бизнес-логикой, так как он даёт больше контроля и упрощает тестирование. Но если вам нужно быстрое прототипирование — Active Record тоже рабочий вариант. Правильный выбор сущности критичен для производительности. Используйте @PrimaryGeneratedColumn('uuid') для распределённых систем, @Index() для часто фильтруемых полей. Репозиторий — это прослойка между бизнес-логикой и БД. Оборачивайте в репозиторий все запросы к сущности: это делает код переиспользуемым и тестируемым.

Декоратор Назначение
@PrimaryGeneratedColumn Автоинкрементный UUID или integer
@Column Простое поле с типом и опциями
@Index Индекс для ускорения запросов
@ManyToOne Связь «многие к одному»
@OneToMany Обратная сторона связи

Пример репозитория с пагинацией:

const postRepository = AppDataSource.getRepository(Post) async function findPosts(opts: { page: number; limit: number; search?: string }) { const { page, limit, search } = opts const qb = postRepository.createQueryBuilder('post') .leftJoinAndSelect('post.author', 'author') .leftJoinAndSelect('post.tags', 'tag') .where('post.published = :published', { published: true }) .orderBy('post.createdAt', 'DESC') .skip((page - 1) * limit) .take(limit) if (search) { qb.andWhere( 'post.title ILIKE :search OR post.content ILIKE :search', { search: `%${search}%` } ) } const [items, total] = await qb.getManyAndCount() return { items, total, pages: Math.ceil(total / limit) } } // Сложные агрегаты const stats = await AppDataSource.query(` SELECT date_trunc('week', created_at) AS week, count(*) AS posts, count(*) FILTER (WHERE published = true) AS published FROM posts WHERE created_at >= now() - interval '90 days' GROUP BY 1 ORDER BY 1 `) 

Почему миграции важны для продакшена?

Согласно официальной документации TypeORM, миграции — единственный безопасный способ управления схемой в production. Миграции позволяют версионировать изменения схемы базы данных и применять их последовательно. TypeORM умеет автоматически генерировать миграции на основе изменений в сущностях. Это экономит до 50% времени на разработку миграций по сравнению с ручным написанием SQL. Пример генерации и применения:

# Генерация миграции из diff схемы npx typeorm migration:generate -n AddUserProfile -d dist/db/data-source.js # Создать пустую миграцию вручную npx typeorm migration:create -n AddIndexes # Применить npx typeorm migration:run -d dist/db/data-source.js # Откатить последнюю npx typeorm migration:revert -d dist/db/data-source.js 
// db/migrations/1234567890-AddUserProfile.ts import { MigrationInterface, QueryRunner } from 'typeorm' export class AddUserProfile1234567890 implements MigrationInterface { public async up(queryRunner: QueryRunner): Promise<void> { await queryRunner.query(` CREATE TABLE profiles ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL UNIQUE REFERENCES users(id) ON DELETE CASCADE, bio TEXT, avatar_url VARCHAR(500), updated_at TIMESTAMPTZ NOT NULL DEFAULT now() ) `) } public async down(queryRunner: QueryRunner): Promise<void> { await queryRunner.query(`DROP TABLE profiles`) } } 

Интеграция с NestJS и подписки на события

В NestJS настройка TypeORM сводится к импорту TypeOrmModule с конфигурацией. Дополнительно можно внедрять репозитории через декоратор @InjectRepository. Subscribers (подписки) позволяют реагировать на изменения сущностей: после вставки обновить поисковый индекс, после публикации — отправить уведомление. Это мощный инструмент, если не злоупотреблять. Пример настройки NestJS:

// app.module.ts import { TypeOrmModule } from '@nestjs/typeorm' @Module({ imports: [ TypeOrmModule.forRootAsync({ inject: [ConfigService], useFactory: (config: ConfigService) => ({ type: 'postgres', url: config.get('DATABASE_URL'), entities: [__dirname + '/**/*.entity{.ts,.js}'], migrations: [__dirname + '/db/migrations/*{.ts,.js}'], migrationsRun: true, synchronize: false, }) }), TypeOrmModule.forFeature([User, Post]) ] }) export class AppModule {} 
Типичные ошибки и как их избежать
  • Synchronize в production — никогда. Используйте миграции.
  • Отсутствие индексов — добавляйте @Index() на поля, по которым часто фильтруете.
  • Игнорирование пула соединений — настройте extra.max и idleTimeoutMillis.
  • N+1 запросы — используйте relations или Query Builder с leftJoinAndSelect.
  • Хранение паролей в сущности — используйте @Column({ select: false }) и хешируйте в @BeforeInsert.

Ориентировочные сроки и стоимость

Базовая настройка TypeORM с сущностями, миграциями и репозиториями: 1–2 дня. Интеграция в NestJS-проект с модулями и тестами: 2–3 дня. Перевод существующего проекта с другого ORM на TypeORM: 3–5 дней. Стоимость базовой конфигурации TypeORM начинается от 35 000 рублей и зависит от сложности проекта. Свяжитесь с нами для оценки — это бесплатно и займёт не более часа.