Налаштування 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
    1246
  • 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 запит TypeORM — класична проблема при роботі з 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 грн і залежить від складності проєкту. Зв'яжіться з нами для оцінки — це безкоштовно і займе не більше години.

TypeORM на GitHub

TypeORM має понад 30 000 зірок на GitHub та понад 400 контриб'юторів, що свідчить про його популярність і активний розвиток.