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

Ручное написание SQL-запросов и синхронизация схемы с кодом часто приводят к ошибкам и нестабильности в production. Мы настраиваем TypeORM под ваш проект — от простого сервера до сложного NestJS-приложения, обеспечивая корректную работу сущностей, миграций и репозиториев. Наша команда реализует настройку под ключ с многолетним опытом и последующей поддержкой, чтобы ваше приложение работало надёжно и масштабировалось вместе с бизнесом.

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

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

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

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

При разработке на 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. Правильная настройка пула соединений сэкономила клиенту около $1.4k–1.9k в год на инфраструктуре. Закажите настройку 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 начинается от $320–460 и зависит от сложности проекта. Свяжитесь с нами для оценки — это займёт не более часа.

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

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

  • Разработка сайта компании B2B ADVANCE
    Разработка сайта компании B2B ADVANCE
    1542
  • Разработка веб-приложения для компании FEEDME
    Разработка веб-приложения для компании FEEDME
    1394
  • Разработка веб-сайта для компании БЕЛФИНГРУПП
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    1081
  • Разработка интернет магазина для компании FURNORO
    Разработка интернет магазина для компании FURNORO
    1369
  • Разработка веб-приложения для компании Enviok
    Разработка веб-приложения для компании Enviok
    1141
  • Разработка веб-сайта для компании ФИКСПЕР
    Разработка веб-сайта для компании ФИКСПЕР
    1060