NestJS en TypeORM in 2026: Migraties, Relaties en Interviewvragen
NestJS TypeORM integratie met TypeORM 1.1 migraties, entity-relaties, repository patterns en veelgestelde interviewvragen voor backend-ontwikkelaars.

NestJS TypeORM blijft een van de beproefde ORM-integraties voor enterprise Node.js backends. Met TypeORM versie 1.0 in mei 2026, gevolgd door de 1.1.x patchserie die verbindingsbeheer en relatiepersistentie verbetert, en NestJS 12 dat de ESM-migratie voltooit, biedt de stack een stabiele basis voor productieapplicaties. Deze gids behandelt de essentiele patronen voor elke backend-ontwikkelaar: migraties, entity-relaties, het repository-pattern en de bijbehorende interviewvragen.
NestJS 12 levert core-pakketten als ESM en vereist Node.js 20.19+ of 22.12+. Het @nestjs/typeorm v12 pakket volgt dezelfde aanpak. TypeORM 1.1.2 repareert verbindingslekken in DataSource.initialize() en corrigeert many-to-many junction row persistentie wanneer relaties niet geladen zijn.
TypeORM-migraties instellen in NestJS 12
De eerste regel voor productiedatabases: gebruik nooit synchronize: true. Auto-sync vergelijkt entity-metadata met het live schema en past wijzigingen direct toe, wat kan leiden tot dataverlies bij het verwijderen van kolommen, typewijzigingen of hernoemde velden. Migraties bieden een versiebeheerd, controleerbaar en omkeerbaar alternatief.
TypeORM 1.x vereist een aparte DataSource-configuratiebestand voor de CLI, gescheiden van de NestJS-moduleconfiguratie. De CLI kan NestJS dependency injection niet oplossen, dus heeft het een zelfstandig entrypoint nodig.
import { DataSource } from 'typeorm';
import { config } from 'dotenv';
config(); // Load .env variables
export default new DataSource({
type: 'postgres',
host: process.env.DB_HOST,
port: parseInt(process.env.DB_PORT || '5432'),
username: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
entities: ['src/**/*.entity.ts'],
migrations: ['src/migrations/*.ts'],
synchronize: false,
});De NestJS-moduleconfiguratie weerspiegelt deze instellingen maar gebruikt het TypeOrmModule.forRootAsync-pattern met dependency injection:
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ConfigModule, ConfigService } from '@nestjs/config';
@Module({
imports: [
ConfigModule.forRoot({ isGlobal: true }),
TypeOrmModule.forRootAsync({
inject: [ConfigService],
useFactory: (config: ConfigService) => ({
type: 'postgres',
host: config.get('DB_HOST'),
port: config.getOrThrow<number>('DB_PORT'),
username: config.get('DB_USER'),
password: config.get('DB_PASSWORD'),
database: config.get('DB_NAME'),
autoLoadEntities: true, // Auto-register entities from feature modules
synchronize: false, // Always false in production
}),
}),
],
})
export class AppModule {}autoLoadEntities: true vervangt de handmatige entities-array door automatisch elke entity te registreren die via TypeOrmModule.forFeature() in feature modules wordt geimporteerd.
Migratie-workflow: genereren, controleren, uitvoeren
TypeORM 1.x levert typeorm-ts-node-commonjs als aanbevolen CLI-runner, ter vervanging van de oudere ts-node ./node_modules/typeorm/cli-aanpak. Voeg deze scripts toe aan package.json:
{
"migration:generate": "typeorm-ts-node-commonjs migration:generate src/migrations/$npm_config_name -d src/config/typeorm.config.ts",
"migration:run": "typeorm-ts-node-commonjs migration:run -d src/config/typeorm.config.ts",
"migration:revert": "typeorm-ts-node-commonjs migration:revert -d src/config/typeorm.config.ts"
}Het generate-commando vergelijkt entity-metadata met de live database en produceert SQL-statements. Controleer de output altijd voor het committen. TypeORM detecteert kolomtoevoegingen, -verwijderingen, typewijzigingen, indexmodificaties en foreign key-wijzigingen, maar mist data-backfills, tabelhernoemingen (die verschijnen als een drop gevolgd door een create), en alles met database-extensies of triggers.
Een hernoemde kolom genereert een DROP + ADD in plaats van een ALTER RENAME. Dit vernietigt bestaande data. Inspecteer altijd de SQL in de up()-methode en pas handmatig aan waar nodig.
Entity-relaties: OneToMany, ManyToOne, ManyToMany
TypeORM entity-relaties mappen direct naar SQL foreign keys met decorators. Het begrijpen van de drie kernrelatietypen en hun opties is fundamenteel voor elke NestJS databasemodule.
Een User met meerdere Order-records demonstreert het meest voorkomende patroon:
import { Entity, PrimaryGeneratedColumn, Column, OneToMany, CreateDateColumn } from 'typeorm';
import { Order } from './order.entity';
@Entity('users')
export class User {
@PrimaryGeneratedColumn('uuid')
id: string;
@Column({ unique: true })
email: string;
@Column()
name: string;
@OneToMany(() => Order, (order) => order.user)
orders: Order[]; // No DB column created here; relation lives on the Order side
@CreateDateColumn()
createdAt: Date;
}import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, JoinColumn } from 'typeorm';
import { User } from './user.entity';
@Entity('orders')
export class Order {
@PrimaryGeneratedColumn('uuid')
id: string;
@Column('decimal', { precision: 10, scale: 2 })
total: number;
@Column({ default: 'pending' })
status: string;
@ManyToOne(() => User, (user) => user.orders, { onDelete: 'CASCADE' })
@JoinColumn({ name: 'user_id' }) // Explicit FK column name
user: User;
}De @ManyToOne-kant bezit de foreign key. @JoinColumn is optioneel op @ManyToOne (TypeORM leidt het af), maar expliciete naamgeving voorkomt verrassingen bij raw queries of migratie-diffs.
Voor many-to-many relaties maakt TypeORM automatisch een junction table:
import { Entity, PrimaryGeneratedColumn, Column, ManyToMany, JoinTable } from 'typeorm';
import { Category } from './category.entity';
@Entity('products')
export class Product {
@PrimaryGeneratedColumn('uuid')
id: string;
@Column()
name: string;
@Column('decimal', { precision: 10, scale: 2 })
price: number;
@ManyToMany(() => Category, (category) => category.products)
@JoinTable({ name: 'product_categories' }) // Owns the junction table
categories: Category[];
}@JoinTable moet op precies een kant van de relatie staan. Het definieert welke entity de junction table bezit en controleert de naam ervan.
Klaar om je Node.js / NestJS gesprekken te halen?
Oefen met onze interactieve simulatoren, flashcards en technische tests.
Repository-pattern en custom repositories
Het NestJS module- en DI-systeem integreert TypeORM repositories via TypeOrmModule.forFeature(). Het injecteren van de standaard Repository<T> dekt standaard CRUD-operaties. Wanneer queries complex worden, kapselen custom repositories die logica in.
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Order } from '../entities/order.entity';
import { OrdersService } from './orders.service';
import { OrdersController } from './orders.controller';
@Module({
imports: [TypeOrmModule.forFeature([Order])],
providers: [OrdersService],
controllers: [OrdersController],
})
export class OrdersModule {}import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Order } from '../entities/order.entity';
@Injectable()
export class OrdersService {
constructor(
@InjectRepository(Order)
private readonly orderRepo: Repository<Order>,
) {}
async findByUser(userId: string): Promise<Order[]> {
return this.orderRepo.find({
where: { user: { id: userId } },
relations: ['user'], // Eager-load the user relation
order: { createdAt: 'DESC' }, // Most recent first
});
}
async findWithFilters(status: string, minTotal: number): Promise<Order[]> {
// QueryBuilder for complex queries
return this.orderRepo
.createQueryBuilder('order')
.leftJoinAndSelect('order.user', 'user')
.where('order.status = :status', { status })
.andWhere('order.total >= :minTotal', { minTotal })
.orderBy('order.total', 'DESC')
.getMany();
}
}De find()-API behandelt eenvoudige queries. De QueryBuilder behandelt joins, subqueries, aggregaties en alles wat fijnmazige SQL-controle vereist. Beide in dezelfde service mixen is volkomen geldig: gebruik find() voor simpele lookups en QueryBuilder wanneer de query niet via de options-API uitgedrukt kan worden.
Transactiebeheer voor data-integriteit
Operaties die meerdere tabellen wijzigen hebben transacties nodig. TypeORM biedt twee benaderingen: de DataSource.transaction()-methode en de QueryRunner-API.
async createOrderWithItems(
userId: string,
items: { productId: string; quantity: number }[],
dataSource: DataSource,
): Promise<Order> {
return dataSource.transaction(async (manager) => {
// All operations use the transactional manager
const order = manager.create(Order, {
user: { id: userId },
total: 0,
status: 'pending',
});
const savedOrder = await manager.save(order);
let total = 0;
for (const item of items) {
const product = await manager.findOneByOrFail(Product, { id: item.productId });
total += product.price * item.quantity;
await manager.save(OrderItem, {
order: savedOrder,
product,
quantity: item.quantity,
unitPrice: product.price,
});
}
savedOrder.total = total;
return manager.save(savedOrder);
});
}De callback-gebaseerde transaction()-methode commit automatisch bij succes en rolt terug bij elke gegooide fout. Elke databaseoperatie binnen de callback moet de meegegeven manager gebruiken in plaats van de geinjecteerde repository, anders draaien die operaties buiten de transactie.
Gebruik DataSource.transaction() voor eenvoudige multi-step operaties. Schakel over naar QueryRunner wanneer handmatige controle over commit/rollback-punten of savepoints vereist is, zoals bij partiele rollbacks in batchverwerking.
Veelgestelde NestJS TypeORM interviewvragen
Deze vragen komen regelmatig voor in backend-ontwikkelaar interviews. Elk antwoord richt zich op de diepgang die verwacht wordt in een technische discussie op senior niveau.
Waarom mag synchronize: true nooit in productie worden gebruikt?
Auto-sync past destructieve schemawijzigingen toe zonder bevestiging. Het verwijderen van een kolom, wijzigen van een type of verwijderen van een index gebeurt direct op live data. Migraties bieden versiebeheer, code review en rollback-mogelijkheid. Het enige veilige gebruik van synchronize is lokale ontwikkeling met wegwerpdata.
Wat is het verschil tussen eager en lazy relaties?
Eager relaties laden automatisch mee bij elke query op de parent entity. Lazy relaties retourneren een Promise en voeren pas een aparte query uit wanneer ze benaderd worden. Eager loading veroorzaakt N+1-achtige overhead wanneer de gerelateerde data niet nodig is. Lazy loading stelt de kosten uit maar kan onverwachte queries diep in de call stack triggeren. De expliciete relations-optie in find() of leftJoinAndSelect in QueryBuilder geeft volledige controle over wat per query geladen wordt.
Hoe werkt cascade in TypeORM-relaties?
Het instellen van cascade: true op een relatie betekent dat het opslaan van de parent entity ook niet-opgeslagen child entities persisteert. cascade: ['insert', 'update'] beperkt het gedrag tot specifieke operaties. Cascades werken op ORM-niveau, niet op databaseniveau. Voor database-niveau cascade deletes, gebruik onDelete: 'CASCADE' op de @ManyToOne-decorator, die een ON DELETE CASCADE-constraint genereert in de migratie.
Wanneer moet een custom repository worden gebruikt in plaats van de standaard Repository<T>?
Custom repositories kapselen complexe querylogica in die niet in services thuishoort. Tekenen om een custom repository te extraheren: dezelfde QueryBuilder-keten verschijnt in meerdere services, de query bevat meerdere joins of subqueries, of de query vereist raw SQL. Simpele find()-aanroepen rechtvaardigen geen custom repository.
Voor meer NestJS-architectuurvragen, zie de complete NestJS guards en interceptors gids.
Klaar om je Node.js / NestJS gesprekken te halen?
Oefen met onze interactieve simulatoren, flashcards en technische tests.
Sources
- TypeORM 1.0.0 Release - ECMAScript 2023 vereiste, Connection verwijdering, striktere validatiestandaarden
- TypeORM 1.1.2 Release - Fix voor verbindingslekken in DataSource.initialize(), many-to-many junction row fixes
- NestJS 12 Release - ESM-migratie, Node.js 20.19+/22.12+ vereiste
- @nestjs/typeorm 12.0.0 - Native ES-modules, CommonJS-compatibiliteit via Node require(esm)
Belangrijke punten voor NestJS TypeORM productie-apps
- Gebruik een apart
DataSource-configuratiebestand voor de TypeORM CLI, onafhankelijk van de NestJS-moduleconfiguratie - Activeer nooit
synchronizein productie; vertrouw op gegenereerde en gecontroleerde migraties voor alle schemawijzigingen - Plaats
@ManyToOneop de entity die de foreign key bezit, en gebruik expliciete@JoinColumn-naamgeving voor duidelijkheid in raw queries en migratie-output - Kies tussen de
find()options-API voor simpele queries enQueryBuildervoor complexe joins, aggregaties en conditionele logica - Wrap multi-table mutaties in transacties met
DataSource.transaction(), en zorg dat elke operatie binnen de callback de transactionelemanagergebruikt - Met TypeORM 1.1.x dat het API-oppervlak stabiliseert en NestJS 12 dat de ESM-migratie voltooit, blijft deze stack een sterke keuze voor enterprise backends die gestructureerde, type-safe databasetoegang vereisen
Begin met oefenen!
Test je kennis met onze gespreksimulatoren en technische tests.
Zie jij de bug in Node.js / NestJS?
Een echt codefragment, een verborgen bug, één poging per dag. Zonder account uit te proberen.

Geschreven door
Anthony Fillion-MailletOprichter van SharpSkill
Al meer dan 10 jaar fullstack-ontwikkelaar. Hij leidt SharpSkill en staat in voor alles wat hier verschijnt.
Bijgewerkt op 21 oktober 2026
Tags
Delen
Gerelateerde artikelen

NestJS + Prisma: de moderne backend-stack voor Node.js
Volledige gids voor het bouwen van een moderne backend-API met NestJS en Prisma. Setup, modellen, services, transacties en best practices uitgelegd.

NestJS: Een complete REST API vanaf nul bouwen
Stap-voor-stap handleiding voor het bouwen van een productieklare REST API met NestJS, TypeScript, Prisma en class-validator. CRUD, validatie, foutafhandeling en interceptors.

Microservices met NestJS in 2026: Architectuur, gRPC en Sollicitatievragen
Een praktische gids voor NestJS microservices-architectuur met gRPC, inclusief servicegrenzen, transport layers, streaming patterns en veelgestelde sollicitatievragen voor 2026.