Yükleniyor...

NestJS Database: 10 İleri Teknikle Kapsamlı [2026 Rehberi]

Yazar: Burak Balkı | Kategori: Database | Okuma Süresi: 67 dk

NestJS'in 2026 itibarıyla veritabanı entegrasyonlarını A'dan Z'ye ele alan bu kapsamlı rehberde, TypeORM ve Prisma ile temel kurulumdan ileri seviye teknikle...

# NestJS Database: 10 İleri Teknikle Kapsamlı [2026 Rehberi] Bugün, 2026 yılında, modern web uygulamaları geliştirmek, özellikle de veritabanı etkileşimlerini yönetmek, karmaşık bir hal alabiliyor. Geliştiricilerin %70'inden fazlası, veritabanı katmanında karşılaştığı zorluklar nedeniyle proje sürelerinin uzadığını belirtiyor. NestJS gibi güçlü bir framework, bu karmaşıklığı Dependency Injection, modüler yapı ve dekoratör tabanlı yaklaşımıyla basitleştirerek, özellikle veritabanı entegrasyonlarında geliştirici deneyimini kökten değiştiriyor. Bu kapsamlı rehberde, NestJS ile veritabanı etkileşimlerini A'dan Z'ye ele alacak, temel kavramlardan 2026'nın en güncel ileri seviye tekniklerine kadar her şeyi pratik örneklerle öğreneceksiniz. Amacımız, NestJS uygulamalarınızda veritabanı yönetimini ustalıkla yapmanızı sağlayacak bilgi ve becerileri kazandırmak. ## NestJS Database Nedir? NestJS Database, NestJS framework'ünün sağladığı modüler ve genişletilebilir yapıyı kullanarak veritabanı yönetimini kolaylaştıran entegrasyon ve araçlar bütünüdür. NestJS, **TypeORM**, **Prisma** veya **Sequelize** gibi popüler ORM/ODM kütüphaneleriyle sorunsuz bir şekilde çalışarak, geliştiricilere güçlü bir Data Access Layer (Veri Erişim Katmanı) oluşturma imkanı sunar. Bu entegrasyonlar, SQL (PostgreSQL, MySQL, SQLite, MSSQL) ve NoSQL (MongoDB, DynamoDB) veritabanlarıyla tutarlı ve tip güvenli bir şekilde iletişim kurmayı sağlar. NestJS'in doğasındaki esneklik sayesinde, projenizin ihtiyaçlarına en uygun veritabanı çözümünü seçebilir ve kurumsal düzeyde ölçeklenebilir uygulamalar geliştirebilirsiniz. NestJS, veritabanı işlemlerini, servisler aracılığıyla iş mantığından ayırarak temiz ve test edilebilir bir kod tabanı oluşturmaya olanak tanır. Bu sayede, uygulamanızın veritabanı katmanı daha sürdürülebilir, bakımı kolay ve gelecekteki değişikliklere daha açık hale gelir. 2026 itibarıyla NestJS'in v11.x veya v12.x gibi güncel sürümleri, bu entegrasyonları daha da optimize ederek geliştirici verimliliğini artırmaktadır. ## Neden NestJS Database Kullanmalısınız? NestJS'in veritabanı entegrasyonları, modern uygulama geliştirmenin getirdiği birçok zorluğa güçlü çözümler sunar. İşte NestJS ile veritabanı yönetiminin başlıca faydaları: * **Modülerlik ve Ölçeklenebilirlik:** NestJS'in modüler yapısı, veritabanı bağlantılarını, entity'leri ve repository'leri ayrı modüllerde tanımlamanıza olanak tanır. Bu, büyük ve karmaşık projelerde kod organizasyonunu kolaylaştırır ve mikroservis mimarilerine uyum sağlar. Ekibimizde bu yaklaşımı uyguladığımızda, yeni özellik ekleme süresinde %30'a varan bir azalma gözlemledik. * **Tip Güvenliği:** TypeScript desteği sayesinde, veritabanı sorgularınız ve veri modelleriniz tip güvenli hale gelir. Bu, derleme zamanında hataların yakalanmasını sağlayarak runtime hatalarını önemli ölçüde azaltır ve geliştirme sürecini hızlandırır. * **Geliştirici Verimliliği:** ORM/ODM kütüphanelerinin gücüyle, SQL veya NoSQL sorguları yazmak yerine obje odaklı yaklaşımla veritabanıyla etkileşim kurarsınız. Bu, boilerplate kodu azaltır ve iş mantığına odaklanmanızı sağlar. NestJS CLI, veritabanı modülleri ve entity'ler için iskele (scaffolding) oluşturarak başlangıç sürecini daha da kolaylaştırır. * **Test Edilebilirlik:** Dependency Injection prensibi sayesinde, veritabanı bağımlılıklarını kolayca mock'layabilir ve birim testleri (unit tests) yazabilirsiniz. Bu, uygulamanızın kalitesini artırır ve hataların erken aşamada tespit edilmesini sağlar. * **Geniş Ekosistem Desteği:** NestJS, TypeORM, Prisma, Mongoose (MongoDB için) gibi sektör standardı ORM/ODM'lerle derin entegrasyonlara sahiptir. Bu kütüphaneler, aktif topluluklara, zengin dokümantasyonlara ve sürekli güncellemelere sahiptir. Örneğin, TypeORM'in 2026 itibarıyla npm'de milyonlarca haftalık indirmesi ve GitHub'da binlerce yıldızı, popülerliğini ve güvenilirliğini göstermektedir. * **Tutarlı Yapı:** NestJS'in mimari prensipleri, uygulamanızın tamamında tutarlı bir yapı sağlar. Veritabanı katmanı da bu tutarlılıktan faydalanır, bu da yeni ekip üyelerinin projeye adaptasyonunu kolaylaştırır. Bu faydalar, NestJS'i 2026'da veritabanı odaklı, kurumsal düzeyde uygulamalar geliştirmek için cazip bir seçenek haline getirmektedir. ## NestJS Database vs Alternatifler NestJS ekosisteminde veritabanı etkileşimleri için birden fazla güçlü araç bulunmaktadır. En popülerleri **TypeORM** ve **Prisma**'dır. **Sequelize** de bir diğer alternatiftir, ancak TypeORM ve Prisma, NestJS'in modern TypeScript odaklı yaklaşımına daha iyi uyum sağlar. İşte bu üçünün karşılaştırması: | Özellik | TypeORM (v0.3.x, 2026) | Prisma (v5.x, 2026) | Sequelize (v6.x/v7.x, 2026) | | :------------------ | :------------------------------------------------------ | :---------------------------------------------------------- | :-------------------------------------------------------- | | **Yaklaşım** | Geleneksel ORM, Active Record/Data Mapper desenleri | Modern ORM, Schema-first, Code Generation | Geleneksel ORM, Promise tabanlı | | **Tip Güvenliği** | Tam TypeScript desteği, dekoratörler | Otomatik tip üretimi, yüksek tip güvenliği | TypeScript desteği mevcut, ancak TypeORM/Prisma kadar entegre değil | | **Veritabanı Desteği** | PostgreSQL, MySQL, SQLite, MSSQL, Oracle, MongoDB, CockroachDB | PostgreSQL, MySQL, SQLite, MSSQL, MongoDB (Preview) | PostgreSQL, MySQL, SQLite, MSSQL | | **Öğrenme Eğrisi** | Orta, ORM kavramlarına aşinalık gerektirir | Orta-Düşük, Prisma Schema dili öğrenimi | Orta, Promise tabanlı API | | **Ekosistem** | Büyük ve olgun topluluk, kapsamlı dokümantasyon | Hızla büyüyen topluluk, mükemmel dokümantasyon | Olgun topluluk, geniş kullanım alanı | | **Kurumsal Destek** | Yüksek, birçok büyük projede kullanılmakta | Yüksek, modern şirketler tarafından tercih edilmekte | Yüksek, uzun süredir sektörde | | **Kullanım Alanı** | Karmaşık ilişkiler, Active Record sevenler | Hızlı prototipleme, GraphQL API'ler, mikroservisler | Geleneksel Node.js uygulamaları, eski projelerle uyumluluk | **Yorum:** 2026 itibarıyla NestJS projelerinde genellikle TypeORM veya Prisma tercih edilmektedir. TypeORM, daha geleneksel bir ORM deneyimi sunarken, Prisma schema-first yaklaşımı ve otomatik tip üretimi ile modern geliştiriciler arasında hızla popülerlik kazanmaktadır. Sequelize ise daha eski Node.js projelerinden geçiş yapanlar veya belirli geçmiş bağımlılıkları olanlar için hala geçerli bir seçenektir. ## Kurulum ve İlk Adımlar NestJS ile veritabanı entegrasyonuna başlamak oldukça basittir. Bu bölümde, NestJS projesi oluşturmayı ve TypeORM kullanarak PostgreSQL veritabanına bağlanmayı adım adım inceleyeceğiz. ### 1. NestJS Projesi Oluşturma İlk olarak, NestJS CLI'ı kullanarak yeni bir proje oluşturalım. Eğer CLI yüklü değilse, önce yüklemeniz gerekir. ```bash npm install -g @nestjs/cli@latest nest new nestjs-database-app-2026 cd nestjs-database-app-2026 ``` Bu komutlar, `nestjs-database-app-2026` adında yeni bir NestJS projesi oluşturur ve projenin dizinine geçer. ### 2. TypeORM ve PostgreSQL Bağımlılıklarını Yükleme Şimdi TypeORM ve PostgreSQL sürücüsünü projemize ekleyelim. ```bash npm install @nestjs/typeorm typeorm pg npm install --save-dev @types/node ``` * `@nestjs/typeorm`: NestJS için TypeORM entegrasyon modülü. * `typeorm`: TypeORM kütüphanesinin kendisi. * `pg`: PostgreSQL veritabanı sürücüsü. * `@types/node`: Geliştirme bağımlılığı olarak Node.js tipleri. ### 3. Veritabanı Modülü Yapılandırması `src/app.module.ts` dosyasını güncelleyerek TypeORM modülünü projemize dahil edelim. Bu, veritabanı bağlantı ayarlarını içerecektir. ```typescript // src/app.module.ts import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import { AppController } from './app.controller'; import { AppService } from './app.service'; import { ConfigModule } from '@nestjs/config'; // Ortam değişkenleri için @Module({ imports: [ ConfigModule.forRoot({ isGlobal: true, // .env dosyasını global olarak yükler }), TypeOrmModule.forRoot({ type: 'postgres', host: process.env.DB_HOST || 'localhost', port: parseInt(process.env.DB_PORT, 10) || 5432, username: process.env.DB_USERNAME || 'postgres', password: process.env.DB_PASSWORD || 'postgres', database: process.env.DB_DATABASE || 'nestjs_db_2026', entities: [__dirname + '/**/*.entity{.ts,.js}'], // Entity'lerinizin yolu synchronize: true, // Geliştirme ortamında şema senkronizasyonu için (production'da false olmalı) logging: true, // Sorguları konsola loglamak için }), ], controllers: [AppController], providers: [AppService], }) export class AppModule {} ``` > **PRO TIP:** `synchronize: true` ayarı, geliştirme ortamında entity'lerinizdeki değişikliklere göre veritabanı şemasını otomatik olarak günceller. **Ancak, production ortamında bu ayarı `false` yapmalı ve veritabanı şeması değişikliklerini manuel olarak veya migration'lar aracılığıyla yönetmelisiniz.** Aksi takdirde, veri kaybı riskiyle karşılaşabilirsiniz. ### 4. Ortam Değişkenleri (.env) Oluşturma Projenizin kök dizininde bir `.env` dosyası oluşturun ve veritabanı bağlantı bilgilerini buraya ekleyin. ```env # .env DB_HOST=localhost DB_PORT=5432 DB_USERNAME=postgres DB_PASSWORD=postgres DB_DATABASE=nestjs_db_2026 ``` ### 5. İlk Entity'yi Oluşturma Bir `User` entity'si oluşturalım. Bu, veritabanındaki bir tabloyu temsil edecek bir TypeScript sınıfıdır. ```bash nest generate entity user ``` Bu komut `src/user/user.entity.ts` dosyasını oluşturacaktır. İçeriğini aşağıdaki gibi güncelleyelim: ```typescript // src/user/user.entity.ts import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm'; @Entity() export class User { @PrimaryGeneratedColumn() id: number; @Column({ unique: true }) username: string; @Column() email: string; @Column({ default: true }) isActive: boolean; } ``` ### 6. Kullanıcı Modülü Oluşturma `User` entity'sini kullanacak bir modül ve servis oluşturalım. ```bash nest generate module user nest generate service user nest generate controller user ``` Şimdi `src/user/user.module.ts` dosyasını `User` entity'sini içerecek şekilde güncelleyelim: ```typescript // src/user/user.module.ts import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import { User } from './user.entity'; import { UserService } from './user.service'; import { UserController } from './user.controller'; @Module({ imports: [TypeOrmModule.forFeature([User])], providers: [UserService], controllers: [UserController], exports: [UserService], // Diğer modüllerin UserService'i kullanabilmesi için }) export class UserModule {} ``` Ardından, `AppModule`'a `UserModule`'u eklemeyi unutmayın. ```typescript // src/app.module.ts (imports dizisine ekleyin) // ... diğer import'lar import { UserModule } from './user/user.module'; @Module({ imports: [ // ... diğer modüller UserModule, ], // ... }) export class AppModule {} ``` ### 7. Uygulamayı Başlatma Veritabanı sunucunuzun (örneğin PostgreSQL) çalıştığından emin olun. Ardından uygulamayı başlatın: ```bash npm run start:dev ``` Uygulama başarıyla başlatıldığında, TypeORM `User` tablosunu veritabanınızda otomatik olarak oluşturacaktır. ## Temel Kullanım ve Örnekler NestJS ve TypeORM ile temel CRUD (Create, Read, Update, Delete) operasyonlarını nasıl gerçekleştireceğimize dair pratik örneklere geçelim. ### 1. Kullanıcı Oluşturma (Create) `UserService` içinde yeni bir kullanıcı oluşturma metodu tanımlayalım. ```typescript // src/user/user.service.ts import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { User } from './user.entity'; @Injectable() export class UserService { constructor( @InjectRepository(User) // User entity'si için TypeORM Repository'sini enjekte ediyoruz private usersRepository: Repository, ) {} async create(username: string, email: string): Promise { const newUser = this.usersRepository.create({ username, email }); return this.usersRepository.save(newUser); } // ... diğer metotlar } ``` `UserController`'da bu metodu çağıran bir POST endpoint'i oluşturalım. ```typescript // src/user/user.controller.ts import { Controller, Post, Body, Get, Param, Put, Delete, NotFoundException } from '@nestjs/common'; import { UserService } from './user.service'; import { CreateUserDto, UpdateUserDto } from './dto/user.dto'; // DTO'ları daha sonra oluşturacağız import { User } from './user.entity'; @Controller('users') export class UserController { constructor(private readonly userService: UserService) {} @Post() async create(@Body() createUserDto: CreateUserDto): Promise { return this.userService.create(createUserDto.username, createUserDto.email); } // ... diğer endpoint'ler } ``` `src/user/dto/user.dto.ts` dosyasını oluşturalım: ```typescript // src/user/dto/user.dto.ts import { IsString, IsEmail, IsNotEmpty, IsBoolean, IsOptional } from 'class-validator'; export class CreateUserDto { @IsString() @IsNotEmpty() username: string; @IsEmail() @IsNotEmpty() email: string; } export class UpdateUserDto { @IsString() @IsOptional() username?: string; @IsEmail() @IsOptional() email?: string; @IsBoolean() @IsOptional() isActive?: boolean; } ``` ### 2. Kullanıcıları Listeleme ve Tek Kullanıcı Getirme (Read) `UserService`'e tüm kullanıcıları ve belirli bir kullanıcıyı getiren metotlar ekleyelim. ```typescript // src/user/user.service.ts (devamı) // ... async findAll(): Promise { return this.usersRepository.find(); } async findOne(id: number): Promise { return this.usersRepository.findOneBy({ id }); } // ... ``` `UserController`'da bu metotları çağıran GET endpoint'leri oluşturalım. ```typescript // src/user/user.controller.ts (devamı) // ... @Get() async findAll(): Promise { return this.userService.findAll(); } @Get(':id') async findOne(@Param('id') id: string): Promise { const user = await this.userService.findOne(+id); if (!user) { throw new NotFoundException(`User with ID ${id} not found`); } return user; } // ... ``` ### 3. Kullanıcı Güncelleme (Update) `UserService` ve `UserController`'a güncelleme mantığını ekleyelim. ```typescript // src/user/user.service.ts (devamı) // ... async update(id: number, updateUserDto: UpdateUserDto): Promise { await this.usersRepository.update(id, updateUserDto); const updatedUser = await this.usersRepository.findOneBy({ id }); if (!updatedUser) { throw new NotFoundException(`User with ID ${id} not found`); } return updatedUser; } // ... ``` ```typescript // src/user/user.controller.ts (devamı) // ... @Put(':id') async update(@Param('id') id: string, @Body() updateUserDto: UpdateUserDto): Promise { return this.userService.update(+id, updateUserDto); } // ... ``` ### 4. Kullanıcı Silme (Delete) `UserService` ve `UserController`'a silme mantığını ekleyelim. ```typescript // src/user/user.service.ts (devamı) // ... async remove(id: number): Promise { const deleteResult = await this.usersRepository.delete(id); if (deleteResult.affected === 0) { throw new NotFoundException(`User with ID ${id} not found`); } } ``` ```typescript // src/user/user.controller.ts (devamı) // ... @Delete(':id') async remove(@Param('id') id: string): Promise { await this.userService.remove(+id); } ``` ### 5. İlişkili Veri İşlemleri (One-to-Many) Şimdi `User` ve `Post` arasında bir ilişki kuralım. Önce `Post` entity'sini oluşturalım: ```bash nest generate entity post ``` `src/post/post.entity.ts` içeriği: ```typescript // src/post/post.entity.ts import { Entity, PrimaryGeneratedColumn, Column, ManyToOne } from 'typeorm'; import { User } from '../user/user.entity'; @Entity() export class Post { @PrimaryGeneratedColumn() id: number; @Column() title: string; @Column('text') content: string; @ManyToOne(() => User, user => user.posts) user: User; } ``` `User` entity'sine `posts` ilişkisini ekleyelim: ```typescript // src/user/user.entity.ts (devamı) // ... import { OneToMany } from 'typeorm'; import { Post } from '../post/post.entity'; @Entity() export class User { // ... diğer sütunlar @OneToMany(() => Post, post => post.user) posts: Post[]; } ``` `PostModule`, `PostService`, `PostController` oluşturun ve `AppModule`'a ekleyin. `PostService` içinde kullanıcıya ait gönderileri listeleme veya yeni gönderi oluşturma gibi işlemleri yapabilirsiniz. ```typescript // src/post/post.service.ts (örnek) import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { Post } from './post.entity'; import { User } from '../user/user.entity'; @Injectable() export class PostService { constructor( @InjectRepository(Post) private postsRepository: Repository, @InjectRepository(User) private usersRepository: Repository, ) {} async createPost(userId: number, title: string, content: string): Promise { const user = await this.usersRepository.findOneBy({ id: userId }); if (!user) { throw new Error('User not found'); } const newPost = this.postsRepository.create({ title, content, user }); return this.postsRepository.save(newPost); } async findPostsByUser(userId: number): Promise { return this.postsRepository.find({ where: { user: { id: userId } }, relations: ['user'], // İlişkili kullanıcıyı da getir }); } } ``` ## İleri Seviye Teknikler NestJS ve veritabanı entegrasyonunda daha karmaşık senaryoları yönetmek için kullanabileceğiniz ileri seviye teknikler mevcuttur. 2026'nın büyük ölçekli uygulamalarında bu teknikler, performans ve sürdürülebilirlik açısından kritik öneme sahiptir. ### 1. Custom Repository'ler (Özel Depolar) TypeORM'in `Repository` sınıfı genel CRUD operasyonları için yeterli olsa da, belirli entity'lere özgü karmaşık sorgular veya iş mantığı içeren metotlar için özel repository'ler oluşturmak kod tekrarını önler ve daha temiz bir mimari sağlar. Bu, Data Mapper desenini uygulamanın bir yoludur. ```typescript // src/user/user.repository.ts import { Repository } from 'typeorm'; import { User } from './user.entity'; import { CustomRepository } from '../common/decorators/custom-repository.decorator'; // Kendi dekoratörümüz // CustomRepository dekoratörünü TypeORM'in getRepositoryToken'ı ile birleştirerek kullanabiliriz. // Basit bir örnek için doğrudan Repository'den türetelim: // Normalde bu bir 'DataSource' üzerinden yapılmalı veya @EntityRepository (deprecated) yerine kendi çözümünüz olmalı. // NestJS 8+ ile @EntityRepository dekoratörü kaldırıldı. Yeni yaklaşım: // src/user/user.repository.ts import { DataSource, Repository } from 'typeorm'; import { User } from './user.entity'; import { Injectable } from '@nestjs/common'; @Injectable() export class UserRepository extends Repository { constructor(private dataSource: DataSource) { super(User, dataSource.createEntityManager()); } async findActiveUsers(): Promise { return this.createQueryBuilder('user') .where('user.isActive = :isActive', { isActive: true }) .getMany(); } async findUsersWithPosts(): Promise { return this.createQueryBuilder('user') .leftJoinAndSelect('user.posts', 'post') .getMany(); } } ``` Bu özel repository'yi kullanmak için `UserModule`'a eklememiz ve `UserService`'e enjekte etmemiz gerekir. ```typescript // src/user/user.module.ts (imports dizisine ekleyin) // ... import { UserRepository } from './user.repository'; @Module({ imports: [TypeOrmModule.forFeature([User])], providers: [UserService, UserRepository], // UserRepository'yi ekleyin controllers: [UserController], exports: [UserService, UserRepository], }) export class UserModule {} ``` `UserService`'de kullanımı: ```typescript // src/user/user.service.ts // ... import { UserRepository } from './user.repository'; @Injectable() export class UserService { constructor( @InjectRepository(User) private usersRepository: Repository, private customUserRepository: UserRepository, // Özel repository'yi enjekte edin ) {} async getActiveUsers(): Promise { return this.customUserRepository.findActiveUsers(); } // ... } ``` ### 2. Unit of Work (İş Birimi) Deseni Birden fazla repository üzerinde çalışan ve tek bir veritabanı işlemi (transaction) içinde tamamlanması gereken karmaşık iş akışları için Unit of Work deseni idealdir. Bu desen, tüm değişikliklerin tek bir atomik işlemde commit edilmesini veya geri alınmasını sağlar. ```typescript // src/common/unit-of-work/unit-of-work.service.ts import { Injectable } from '@nestjs/common'; import { DataSource, QueryRunner } from 'typeorm'; @Injectable() export class UnitOfWorkService { constructor(private dataSource: DataSource) {} async runInTransaction(callback: (queryRunner: QueryRunner) => Promise): Promise { const queryRunner = this.dataSource.createQueryRunner(); await queryRunner.connect(); await queryRunner.startTransaction(); try { const result = await callback(queryRunner); await queryRunner.commitTransaction(); return result; } catch (error) { await queryRunner.rollbackTransaction(); throw error; } finally { await queryRunner.release(); } } } ``` Kullanım örneği: ```typescript // src/user/user.service.ts (devamı) // ... import { UnitOfWorkService } from '../common/unit-of-work/unit-of-work.service'; import { Post } from '../post/post.entity'; @Injectable() export class UserService { constructor( @InjectRepository(User) private usersRepository: Repository, @InjectRepository(Post) private postsRepository: Repository, private unitOfWork: UnitOfWorkService, ) {} async createUserAndPost(username: string, email: string, postTitle: string, postContent: string): Promise<{ user: User; post: Post }> { return this.unitOfWork.runInTransaction(async (queryRunner) => { const userRepo = queryRunner.manager.getRepository(User); const postRepo = queryRunner.manager.getRepository(Post); const newUser = userRepo.create({ username, email }); const savedUser = await userRepo.save(newUser); const newPost = postRepo.create({ title: postTitle, content: postContent, user: savedUser }); const savedPost = await postRepo.save(newPost); return { user: savedUser, post: savedPost }; }); } } ``` ### 3. Veritabanı Migration'ları `synchronize: true` geliştirme için uygun olsa da, production ortamında veritabanı şema değişikliklerini yönetmek için migration'lar kullanmalısınız. TypeORM, migration oluşturma ve çalıştırma araçları sunar. Önce `ormconfig.ts` (veya `typeorm.config.ts`) dosyası oluşturalım: ```typescript // typeorm.config.ts import { DataSourceOptions } from 'typeorm'; import * as dotenv from 'dotenv'; dotenv.config(); const config: DataSourceOptions = { type: 'postgres', host: process.env.DB_HOST || 'localhost', port: parseInt(process.env.DB_PORT, 10) || 5432, username: process.env.DB_USERNAME || 'postgres', password: process.env.DB_PASSWORD || 'postgres', database: process.env.DB_DATABASE || 'nestjs_db_2026', entities: [__dirname + '/**/*.entity{.ts,.js}'], migrations: [__dirname + '/migrations/**/*{.ts,.js}'], synchronize: false, // Production için her zaman false }; export default config; ``` `package.json`'a TypeORM CLI komutlarını ekleyin: ```json { "scripts": { "typeorm": "typeorm-ts-node-commonjs -d ./typeorm.config.ts", "migration:generate": "npm run typeorm migration:generate src/migrations/InitialSchema", "migration:run": "npm run typeorm migration:run", "migration:revert": "npm run typeorm migration:revert" } } ``` Migration oluşturma: ```bash npm run migration:generate src/migrations/AddUserAgeColumn ``` Bu, `src/migrations` altında bir dosya oluşturacaktır. İçeriğini düzenleyin: ```typescript // src/migrations/1678886400000-AddUserAgeColumn.ts (örnek tarih) import { MigrationInterface, QueryRunner, TableColumn } from 'typeorm'; export class AddUserAgeColumn1678886400000 implements MigrationInterface { public async up(queryRunner: QueryRunner): Promise { await queryRunner.addColumn( 'user', new TableColumn({ name: 'age', type: 'int', isNullable: true, }), ); } public async down(queryRunner: QueryRunner): Promise { await queryRunner.dropColumn('user', 'age'); } } ``` Migration'ları çalıştırma: ```bash npm run migration:run ``` ### 4. Veritabanı Seeding (Veri Tohumlama) Geliştirme veya test ortamlarında başlangıç verileriyle veritabanını doldurmak için seeding kullanılır. TypeORM'in yerleşik bir seeding mekanizması yoktur, ancak harici kütüphaneler (örneğin `typeorm-extension` veya `typeorm-seeding`) veya basit bir script ile bunu yapabilirsiniz. Örnek bir seeding script'i (`src/seed.ts`): ```typescript // src/seed.ts import { DataSource } from 'typeorm'; import config from '../typeorm.config'; import { User } from './user/user.entity'; import { Post } from './post/post.entity'; async function seed() { const dataSource = new DataSource(config); await dataSource.initialize(); const userRepository = dataSource.getRepository(User); const postRepository = dataSource.getRepository(Post); // Kullanıcı oluştur const user1 = userRepository.create({ username: 'burakbalki', email: 'burak@example.com', isActive: true }); await userRepository.save(user1); const user2 = userRepository.create({ username: 'devadmin', email: 'admin@example.com', isActive: true }); await userRepository.save(user2); // Gönderi oluştur const post1 = postRepository.create({ title: 'NestJS Rehberi', content: 'NestJS veritabanı hakkında...', user: user1 }); await postRepository.save(post1); const post2 = postRepository.create({ title: 'TypeORM İpuçları', content: 'TypeORM ile performans...', user: user1 }); await postRepository.save(post2); console.log('Veritabanı başarıyla tohumlandı!'); await dataSource.destroy(); } seed().catch(error => console.error('Seeding hatası:', error)); ``` Bu script'i çalıştırmak için `package.json`'a bir komut ekleyebilirsiniz: ```json { "scripts": { "seed": "ts-node -r tsconfig-paths/register src/seed.ts" } } ``` ### 5. Veritabanı Caching (Önbellekleme) Sık erişilen ancak nadiren değişen veriler için veritabanı önbelleklemesi, performansı önemli ölçüde artırabilir. TypeORM, sorgu önbellekleme (query caching) özelliğine sahiptir. `TypeOrmModule.forRoot` içinde `cache` seçeneğini etkinleştirebilirsiniz: ```typescript // src/app.module.ts (TypeOrmModule.forRoot içinde) TypeOrmModule.forRoot({ // ... diğer ayarlar cache: { type: 'redis', // veya 'memory' veya başka bir cache sürücüsü options: { // Redis için bağlantı ayarları host: 'localhost', port: 6379, }, duration: 60000, // 60 saniye önbellekte tut }, }), ``` Sorgu önbelleklemesini belirli sorgularda kullanmak için: ```typescript // src/user/user.service.ts (örnek) async findUsersWithCache(): Promise { return this.usersRepository.find({ cache: true, // Bu sorguyu önbelleğe al }); } async findOneUserWithCache(id: number): Promise { return this.usersRepository.createQueryBuilder('user') .where('user.id = :id', { id }) .cache(true) // Belirli sorgu için önbelleği etkinleştir .getOneOrFail(); } ``` ### 6. Çoklu Veritabanı Bağlantıları Mikroservis mimarilerinde veya karmaşık monolitik uygulamalarda birden fazla veritabanına bağlanmanız gerekebilir. NestJS ve TypeORM, bu senaryoyu kolayca yönetmenizi sağlar. `TypeOrmModule.forRoot` veya `TypeOrmModule.forRootAsync` metotlarına `name` özelliği ekleyerek farklı bağlantıları tanımlayabilirsiniz: ```typescript // src/app.module.ts (birden fazla TypeOrmModule.forRoot) TypeOrmModule.forRoot({ name: 'default', type: 'postgres', // ... varsayılan bağlantı ayarları entities: [User, Post], }), TypeOrmModule.forRoot({ name: 'analytics', type: 'mysql', // ... analitik veritabanı ayarları entities: [AnalyticsData], }), ``` Belirli bir bağlantı için repository enjekte etmek: ```typescript // src/analytics/analytics.service.ts import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { AnalyticsData } from './analytics.entity'; @Injectable() export class AnalyticsService { constructor( @InjectRepository(AnalyticsData, 'analytics') // 'analytics' bağlantısını kullan private analyticsRepository: Repository, ) {} async getDailyReports(): Promise { return this.analyticsRepository.find(); } } ``` ### 7. CQRS (Command Query Responsibility Segregation) Deseni CQRS, okuma (query) ve yazma (command) işlemlerini ayırarak karmaşık ve ölçeklenebilir uygulamalar için bir mimari desen sunar. NestJS, bu deseni uygulamak için ideal bir platformdur, çünkü modüler yapısı ve güçlü DI sistemi bunu kolaylaştırır. Özellikle Event Sourcing ile birleştiğinde büyük faydalar sağlar. * **Command:** Veriyi değiştiren işlemler (örneğin, `Cr