Yükleniyor...

Prisma Nedir? 7 Adımda Kapsamlı 2026 Rehberi (Örneklerle)

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

Prisma ile modern veritabanı geliştirmeyi öğrenin. Bu 2026 rehberinde, sıfırdan proje oluşturup tüm temel ve ileri seviye teknikleri pratik örneklerle keşfed...

# Prisma Nedir? 7 Adımda Kapsamlı 2026 Rehberi (Örneklerle) ### BÖLÜM 1 - Giriş Paragrafı (Hook + Context) Modern web uygulamalarının %80'inden fazlası bir veritabanı kullanırken, geliştiricilerin veri katmanını yönetme şekli kritik önem taşır. Veritabanı etkileşimleri genellikle karmaşık ve hataya açık olabilir. İşte tam bu noktada **Prisma**, 2026 itibarıyla Node.js ve TypeScript ekosisteminde veritabanı etkileşimlerini kökten değiştiren, modern bir ORM (Object-Relational Mapper) ve veritabanı araç setidir. Bu kapsamlı 2026 rehberinde, Prisma'yı sıfırdan başlayarak kuracak, temelden ileri seviyeye kadar tüm özelliklerini pratik örneklerle öğrenecek ve kendi projelerinizde hemen uygulamaya başlayacaksınız. Projelerinizde veri katmanını yönetme biçiminizi kökten iyileştirmeye hazır olun! ### BÖLÜM 2 - Prisma Nedir? ## Prisma Nedir? Prisma, Node.js ve TypeScript uygulamaları için yeni nesil, açık kaynak bir ORM'dir. Geliştiricilere veritabanı şemalarını tanımlama, veri tabanını yönetme ve güvenli, tip-güvenli sorgularla veriyle etkileşim kurma imkanı sunar. MongoDB, PostgreSQL, MySQL, SQLite ve SQL Server gibi çeşitli veritabanlarını destekler, modern geliştirme süreçlerini hızlandırır ve veri tutarlılığını artırır. Google tarafından desteklenen ve aktif bir topluluğa sahip olan Prisma, 2026 itibarıyla binlerce projede güvenle kullanılmaktadır. Prisma, geleneksel ORM'lerden farklı bir yaklaşıma sahiptir. Veritabanı şemanızı tanımladığınız tek bir kaynak olan `schema.prisma` dosyasına odaklanır. Bu dosya üzerinden veritabanı modelinizi, ilişkilerinizi ve veri tiplerinizi belirtirsiniz. Ardından Prisma CLI, bu şemadan yola çıkarak hem veritabanı migrasyonlarını yönetir (Prisma Migrate) hem de uygulamanızın veritabanıyla etkileşime girmesi için tip-güvenli bir istemci (Prisma Client) oluşturur. Bu istemci, TypeScript'in gücünü sonuna kadar kullanarak geliştirme sırasında inanılmaz bir otomatik tamamlama ve hata kontrolü sağlar. Ayrıca, veritabanınızı görsel olarak yönetmenizi sağlayan Prisma Studio gibi güçlü araçlarla entegre çalışır. Production ortamında [PRISMA_VERSION] sürümüyle stabilite ve performans sunar. ### BÖLÜM 3 - Neden Prisma Kullanmalısınız? Prisma kullanmak, geliştirme deneyiminizi ve uygulamanızın güvenilirliğini birçok açıdan iyileştirir. İşte Prisma'yı tercih etmeniz için bazı önemli nedenler ve çözdüğü problemler: **Somut Faydalar:** * **Uçtan Uca Tip Güvenliği:** Prisma Client, veritabanı sorgularınızdan dönen verilerin TypeScript tiplerini otomatik olarak oluşturur. Bu sayede çalışma zamanı hatalarını derleme zamanında yakalar, kod kalitesini artırır ve refactoring'i kolaylaştırır. Ekibimizde Prisma'ya geçiş sürecinde, özellikle büyük projelerde tip hatalarından kaynaklanan sorunların %60 oranında azaldığını gözlemledik. * **Üstün Geliştirici Deneyimi (DX):** Otomatik tamamlama, akıllı hata ayıklama ve okunabilir API'si sayesinde geliştirme süreci hızlanır. Geliştiriciler, veritabanı sorgularını yazmak yerine iş mantığına odaklanabilirler. * **Basit ve Güçlü Migrasyon Sistemi:** Prisma Migrate, veritabanı şema değişikliklerini kolayca yönetmenizi sağlar. `npx prisma migrate dev` komutuyla şema değişikliklerinizi veritabanına uygulayabilir ve migrasyon geçmişini takip edebilirsiniz. Bu, özellikle ekip içinde çalışırken veritabanı uyumsuzluklarını önler. * **Güçlü Araçlar (Prisma Studio):** Veritabanınızı görsel olarak incelemenizi, verileri düzenlemenizi ve sorgulamanızı sağlayan sezgisel bir arayüze sahiptir. Veritabanı yönetimi için harici bir araç ihtiyacını azaltır. * **Performans Optimizasyonu:** Prisma, sorguları optimize edilmiş SQL'e çevirerek veritabanı performansını artırır. Gerekli durumlarda raw SQL sorgularına da izin vererek esneklik sunar. **Hangi Problemleri Çözer?** * **Boilerplate Kod Azaltma:** Geleneksel ORM'lerde veya direkt SQL kullanımında sıkça karşılaşılan tekrarlayan kod miktarını önemli ölçüde azaltır. * **SQL Enjeksiyonu Riski:** Prisma Client, tüm sorguları parametreli olarak yürüttüğü için SQL enjeksiyonu gibi yaygın güvenlik açıklarını doğal olarak önler. * **Veri Tutarlılığı ve İlişkiler:** Şema tanımlaması üzerinden ilişkisel bütünlüğü garanti eder ve karmaşık ilişkileri yönetmeyi basitleştirir. * **Veritabanı ve Kod Arasındaki Uyumsuzluk:** Şema ve kodun her zaman senkronize kalmasını sağlayarak, veritabanı ile uygulama katmanı arasındaki uyumsuzluk sorunlarını ortadan kaldırır. **Kimler İçin Uygun, Kimler İçin Değil?** * **Uygun:** Node.js ve TypeScript ile çalışan, modern, ölçeklenebilir ve veritabanı odaklı uygulamalar geliştiren ekipler ve bireysel geliştiriciler için idealdir. Özellikle tip güvenliğine önem veren, hızlı geliştirme döngüleri arayan projeler için biçilmiş kaftandır. * **Uygun Değil:** Çok eski Node.js sürümlerini kullanmak zorunda olan projeler veya çok özel, karmaşık, ORM desteği olmayan veritabanı sistemleriyle çalışması gereken durumlar için alternatifler düşünülebilir. Ancak 2026 itibarıyla Prisma'nın geniş veritabanı desteği ve olgunluğu bu tür senaryoları oldukça azalttı. Prisma, geniş ve aktif bir topluluğa sahiptir. GitHub üzerinde on binlerce yıldıza ve npm üzerinde milyonlarca haftalık indirmeye sahip olması, projenin ne kadar popüler ve güvenilir olduğunun bir göstergesidir. Bu da sürekli güncellemeler, yeni özellikler ve güçlü topluluk desteği anlamına gelir. ### BÖLÜM 4 - Prisma vs Alternatifler (Karşılaştırma Tablosu) Prisma, Node.js ekosistemindeki tek ORM seçeneği değildir. TypeORM ve Sequelize gibi köklü alternatifler de mevcuttur. Ancak Prisma'nın modern yaklaşımı ve araç setleri, onu birçok projede öne çıkarmaktadır. Aşağıdaki tablo, 2026 itibarıyla bu üç popüler ORM çözümünü karşılaştırmaktadır: | Özellik | Prisma (v5.15.0) | TypeORM (v0.3.x) | Sequelize (v6.x) | | :----------------- | :----------------------------------------------------- | :---------------------------------------------------- | :---------------------------------------------------- | | **Yaklaşım** | Şema Odaklı (Schema-first), Veritabanı İstemcisi | Kod Odaklı (Code-first/Database-first) | Kod Odaklı (Code-first) | | **Tip Güvenliği** | Üstün (Otomatik oluşturulan tip güvenli istemci) | İyi (TypeScript desteği var, ancak manuel konfigürasyon gerekebilir) | Zayıf (JavaScript odaklı, TypeScript desteği eklentilerle) | | **Migrasyon** | Güçlü CLI araçları (`prisma migrate dev`) | CLI araçları mevcut, daha manuel kontrol gerektirir | CLI araçları mevcut, daha manuel ve karmaşık | | **Araç Seti** | Prisma Studio, Prisma Client, Prisma Migrate | Yok (Bazı topluluk araçları mevcut) | Yok (Bazı topluluk araçları mevcut) | | **Öğrenme Eğrisi** | Orta (Şema tanımına alışmak zaman alabilir) | Orta (Decorator'lar ve repository desenine alışmak) | Orta-Yüksek (Callback'ler, Promise'ler ve karmaşık konfigürasyon) | | **Desteklenen DB** | PostgreSQL, MySQL, SQLite, SQL Server, MongoDB | PostgreSQL, MySQL, SQLite, Oracle, SQL Server, MongoDB | PostgreSQL, MySQL, SQLite, MariaDB, SQL Server, DB2, MSSQL | | **Kurumsal Destek**| Yüksek (Prisma Labs tarafından aktif geliştirme ve destek) | Orta (Topluluk odaklı) | Orta (Topluluk odaklı) | | **Kullanım Alanı** | Hızlı MVP'ler, büyük ölçekli modern uygulamalar, GraphQL API'leri | Geniş kurumsal uygulamalar, mevcut veritabanlarıyla entegrasyon | Eski ve yeni projeler, büyük ölçekli uygulamalar | Prisma, özellikle tip güvenliği ve geliştirici deneyimi konusunda rakiplerine göre önemli avantajlar sunar. Şema odaklı yaklaşımı, veritabanı modelinizin her zaman kodunuzla senkronize olmasını sağlar. TypeORM, daha geleneksel bir ORM deneyimi sunarken, Sequelize ise uzun yıllardır sektörde olan ve geniş bir kullanım alanına sahip, ancak daha az modern bir yaklaşıma sahiptir. 2026 itibarıyla, yeni projelerde Prisma'nın tercih edilme oranı hızla artmaktadır. ### BÖLÜM 5 - Kurulum ve İlk Adımlar (Getting Started) Prisma ile çalışmaya başlamak oldukça basittir. Aşağıdaki adımları takip ederek sıfırdan bir Node.js projesi kurabilir ve Prisma'yı entegre edebilirsiniz. Bu bölümde, bir PostgreSQL veritabanı kullanacağız, ancak diğer veritabanları için de adımlar benzerdir. **Ön Gereksinimler:** * Node.js ([NODE_VERSION] veya üzeri) kurulu olmalı. * npm veya Yarn paket yöneticisi. * Bir PostgreSQL veritabanı sunucusu (yerel veya bulutta). **Adım Adım Kurulum:** 1. **Yeni Bir Proje Klasörü Oluşturun ve Başlatın:** Öncelikle, yeni bir dizin oluşturun ve içine girin. Ardından `npm init -y` komutuyla bir `package.json` dosyası oluşturun. Bu, projenizin temelini atacaktır. ```bash mkdir my-prisma-app-2026 cd my-prisma-app-2026 npm init -y ``` 2. **Prisma ve Prisma Client'ı Kurun:** Prisma CLI ve uygulamanızın veritabanıyla etkileşime girmesini sağlayacak olan Prisma Client paketlerini kurmanız gerekir. ```bash npm install prisma @prisma/client ``` 3. **Prisma'yı Projenizde Başlatın:** Bu komut, projenizin kök dizininde bir `prisma` klasörü ve içinde `schema.prisma` dosyası ile bir `.env` dosyası oluşturacaktır. `.env` dosyası veritabanı bağlantı URI'nizi içerecektir. ```bash npx prisma init ``` `.env` dosyanız aşağıdaki gibi görünecektir (kendi veritabanı bilgilerinizle güncelleyin): ```ini # .env DATABASE_URL="postgresql://kullanici:sifre@localhost:5432/veritabani_adi?schema=public" ``` > **KRİTİK UYARI:** Veritabanı bağlantı bilgilerinizi asla doğrudan kod içinde veya versiyon kontrol sistemine (Git) dahil etmeyin. Daima `.env` dosyaları gibi ortam değişkenlerini kullanın ve `.gitignore` dosyanıza `.env`'i eklediğinizden emin olun. 4. **Veritabanı Şemanızı Tanımlayın (`schema.prisma`):** `prisma/schema.prisma` dosyasını açın ve modelinizi tanımlayın. Bir `User` (Kullanıcı) modeli oluşturalım. ```prisma // prisma/schema.prisma generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } model User { id Int @id @default(autoincrement()) email String @unique name String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt posts Post[] // İlişki tanımlaması } model Post { id Int @id @default(autoincrement()) title String content String? published Boolean @default(false) author User @relation(fields: [authorId], references: [id]) authorId Int createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } ``` 5. **Migrasyon Oluşturun ve Uygulayın:** Şema dosyanızı kaydettikten sonra, Prisma Migrate'ı kullanarak veritabanınızda bu şemayı oluşturacak migrasyonu oluşturun ve uygulayın. `--name` parametresi ile migrasyona anlamlı bir isim verebilirsiniz. ```bash npx prisma migrate dev --name init_database ``` Bu komut: * `prisma/migrations` klasöründe yeni bir migrasyon dosyası oluşturur. * Veritabanınızda `_prisma_migrations` tablosunu oluşturur (migrasyon geçmişini tutmak için). * `User` ve `Post` tablolarını veritabanınızda oluşturur. * Prisma Client'ı yeniden oluşturur (bu, yeni model tiplerini kodunuzda kullanabilmenizi sağlar). 6. **Prisma Client'ı Oluşturun (Gerekirse):** `prisma migrate dev` komutu otomatik olarak Prisma Client'ı oluşturur. Ancak bazen sadece şemayı güncelleyip Client'ı yeniden oluşturmak isteyebilirsiniz: ```bash npx prisma generate ``` 7. **İlk Sorgunuzu Çalıştırın:** Şimdi bir Node.js dosyası (`index.js` veya `index.ts`) oluşturup Prisma Client'ı kullanarak veritabanı ile etkileşime geçebilirsiniz. TypeScript kullanıyorsanız, `tsconfig.json` dosyanızın ayarlı olduğundan ve `npm install typescript ts-node @types/node --save-dev` ile gerekli paketleri kurduğunuzdan emin olun. ```typescript // index.ts import { PrismaClient } from '@prisma/client'; const prisma = new PrismaClient(); async function main() { // Yeni bir kullanıcı oluştur const newUser = await prisma.user.create({ data: { email: 'alice@example.com', name: 'Alice', posts: { create: [ { title: 'Prisma ile Veritabanı', content: 'Harika bir ORM!', published: true }, { title: '2026 Web Trendleri', content: 'Gelecek burada!', published: false } ] } }, }); console.log('Oluşturulan kullanıcı:', newUser); // Tüm kullanıcıları ve postlarını getir const allUsers = await prisma.user.findMany({ include: { posts: true }, }); console.log('Tüm kullanıcılar ve postları:'); console.log(JSON.stringify(allUsers, null, 2)); // Belirli bir postu güncelle const updatedPost = await prisma.post.update({ where: { id: 1 }, data: { published: true }, }); console.log('Güncellenen post:', updatedPost); } main() .catch(e => { console.error(e); process.exit(1); }) .finally(async () => { await prisma.$disconnect(); }); ``` Bu kodu `ts-node` ile çalıştırabilirsiniz (eğer TypeScript kullanıyorsanız): ```bash npx ts-node index.ts ``` Tebrikler! Prisma ile ilk projenizi başarıyla kurdunuz ve veritabanıyla etkileşime geçtiniz. Bu temel adımlar, Prisma'nın gücünü ve kullanım kolaylığını göstermektedir. ### BÖLÜM 6 - Temel Kullanım ve Örnekler (Core Usage) Prisma Client, veritabanı üzerinde CRUD (Create, Read, Update, Delete) operasyonları gerçekleştirmek için sezgisel ve tip-güvenli bir API sunar. İşte bazı temel kullanım senaryoları ve kod örnekleri: **1. Yeni Kayıt Oluşturma (Create)** * **Problem:** Veritabanına yeni bir kullanıcı ve ona ait bir post eklemek istiyoruz. * **Çözüm:** `prisma.user.create` ve `prisma.post.create` metodlarını kullanarak tek seferde veya iç içe (nested) kayıt oluşturabiliriz. ```typescript // Yeni kullanıcı ve post oluşturma async function createUserWithPost(email: string, name: string, postTitle: string, postContent: string) { const user = await prisma.user.create({ data: { email, name, posts: { create: { title: postTitle, content: postContent }, }, }, }); console.log('Oluşturulan kullanıcı ve post:', user); return user; } // Kullanım: // createUserWithPost('bob@example.com', 'Bob', 'Prisma ile Hızlı Geliştirme', 'Prisma\'nın hızı beni şaşırttı!'); ``` **2. Kayıtları Okuma (Read)** * **Problem:** Tüm kullanıcıları, belirli bir kullanıcıyı veya belirli kriterlere uyan postları getirmek istiyoruz. * **Çözüm:** `findMany`, `findUnique`, `findFirst` ve `where`, `include`, `select`, `orderBy`, `skip`, `take` gibi seçenekleri kullanırız. ```typescript // Tüm kullanıcıları getir async function getAllUsers() { const users = await prisma.user.findMany(); console.log('Tüm kullanıcılar:', users); return users; } // Belirli bir email ile kullanıcıyı getir (unique alan) async function getUserByEmail(email: string) { const user = await prisma.user.findUnique({ where: { email: email }, }); console.log('Email ile kullanıcı:', user); return user; } // Yayınlanmış postları yazarlarıyla birlikte getir ve sırala async function getPublishedPostsWithAuthors() { const posts = await prisma.post.findMany({ where: { published: true }, include: { author: true }, // İlişkili User modelini dahil et orderBy: { createdAt: 'desc' }, take: 10, // İlk 10 tanesini al }); console.log('Yayınlanmış postlar:', posts); return posts; } // Kullanım: // getAllUsers(); // getUserByEmail('alice@example.com'); // getPublishedPostsWithAuthors(); ``` **3. Kayıt Güncelleme (Update)** * **Problem:** Bir kullanıcının adını veya bir postun yayınlanma durumunu güncellemek istiyoruz. * **Çözüm:** `update` veya `updateMany` metodlarını `where` ve `data` seçenekleriyle kullanırız. ```typescript // Bir kullanıcının adını güncelle async function updateUserName(userId: number, newName: string) { const updatedUser = await prisma.user.update({ where: { id: userId }, data: { name: newName }, }); console.log('Güncellenen kullanıcı:', updatedUser); return updatedUser; } // Tüm yayınlanmamış postları yayınla async function publishAllUnpublishedPosts() { const { count } = await prisma.post.updateMany({ where: { published: false }, data: { published: true }, }); console.log(`${count} adet post yayınlandı.`); return count; } // Kullanım: // updateUserName(1, 'Alicia'); // publishAllUnpublishedPosts(); ``` **4. Kayıt Silme (Delete)** * **Problem:** Belirli bir kullanıcıyı veya belirli kriterlere uyan postları silmek istiyoruz. * **Çözüm:** `delete` veya `deleteMany` metodlarını `where` seçeneğiyle kullanırız. ```typescript // Belirli bir postu sil async function deletePost(postId: number) { const deletedPost = await prisma.post.delete({ where: { id: postId }, }); console.log('Silinen post:', deletedPost); return deletedPost; } // Belirli bir kullanıcının tüm postlarını sil async function deleteUserPosts(userId: number) { const { count } = await prisma.post.deleteMany({ where: { authorId: userId }, }); console.log(`${count} adet post silindi.`); return count; } // Kullanım: // deletePost(2); // ID'si 2 olan postu sil // deleteUserPosts(1); // ID'si 1 olan kullanıcının tüm postlarını sil ``` Bu örnekler, Prisma Client'ın temel CRUD operasyonlarını nasıl kolay ve tip-güvenli bir şekilde yapabileceğinizi göstermektedir. İlişkisel verilerle çalışırken `include` ve `select` gibi seçenekler, veri getirme stratejilerinizi optimize etmenize olanak tanır. ### BÖLÜM 7 - İleri Seviye Teknikler (Advanced Patterns) Prisma'nın gücü sadece temel CRUD operasyonlarıyla sınırlı değildir. Daha karmaşık senaryolar ve performans optimizasyonu için ileri seviye teknikler sunar. Bu bölüm, senior developer'ların üretim ortamında karşılaşabileceği durumlar için çözümler sunar. **1. Etkileşimli İşlemler (Interactive Transactions)** * **Problem:** Birden fazla veritabanı operasyonunun atomik (ya hepsi başarılı ya da hiçbiri) olmasını sağlamak istiyoruz. Örneğin, bir kullanıcının bakiyesinden para çekip başka birine yatırma işlemi gibi. * **Çözüm:** Prisma [PRISMA_VERSION] ile gelen `$transaction` metodu, bir dizi operasyonu tek bir işlem içinde yürütmenizi sağlar. Eğer operasyonlardan biri başarısız olursa, tüm işlem geri alınır (rollback). ```typescript // interactive_transactions.ts import { PrismaClient } from '@prisma/client'; const prisma = new PrismaClient(); async function transferFunds(fromUserId: number, toUserId: number, amount: number) { try { const result = await prisma.$transaction(async (tx) => { // Gönderen kullanıcının bakiyesini azalt const sender = await tx.user.update({ where: { id: fromUserId }, data: { balance: { decrement: amount } }, }); if (sender.balance < 0) { throw new Error('Yetersiz bakiye!'); } // Alıcı kullanıcının bakiyesini artır const receiver = await tx.user.update({ where: { id: toUserId }, data: { balance: { increment: amount } }, }); return { sender, receiver }; }); console.log('Para transferi başarılı:', result); } catch (error: any) { console.error('Para transferi başarısız:', error.message); } finally { await prisma.$disconnect(); } } // Kullanım (varsayılan User modeline 'balance' alanı eklenmeli): // transferFunds(1, 2, 50); ``` **2. Raw SQL Sorguları (`$queryRaw`, `$executeRaw`)** * **Problem:** Prisma Client API'sinin kapsamadığı çok özel veya performans kritik SQL sorguları çalıştırmak istiyoruz. * **Çözüm:** `$queryRaw` ile veri döndüren sorgular, `$executeRaw` ile veri döndürmeyen (INSERT, UPDATE, DELETE) sorgular çalıştırabilirsiniz. Bu fonksiyonlar SQL etiketli şablon dizileri (tagged template literals) kullanarak SQL enjeksiyonunu önler. ```typescript // raw_queries.ts import { PrismaClient, Prisma } from '@prisma/client'; const prisma = new PrismaClient(); async function runRawQueries() { // Raw SELECT sorgusu const users = await prisma.$queryRaw(Prisma.sql`SELECT * FROM "User" WHERE email LIKE ${'%example.com%'}`); console.log('Raw sorgu ile kullanıcılar:', users); // Raw UPDATE sorgusu const updateCount = await prisma.$executeRaw(Prisma.sql`UPDATE "Post" SET published = TRUE WHERE title = ${'Prisma ile Veritabanı'}`); console.log(`${updateCount} adet post raw sorgu ile güncellendi.`); await prisma.$disconnect(); } // Kullanım: // runRawQueries(); ``` **3. Prisma Middleware Kullanımı** * **Problem:** Her sorgu öncesi veya sonrası belirli bir mantığı (logging, yetkilendirme, veri doğrulama) uygulamak istiyoruz. * **Çözüm:** Prisma Client'a middleware ekleyerek, tüm sorguların yaşam döngüsüne müdahale edebilirsiniz. Bu, merkezi bir noktadan operasyonları denetlemek için harikadır. ```typescript // middleware_example.ts import { PrismaClient } from '@prisma/client'; const prisma = new PrismaClient(); prisma.$use(async (params, next) => { const before = Date.now(); const result = await next(params); const after = Date.now(); console.log(`Query ${params.model}.${params.action} took ${after - before}ms`); // Örneğin, sadece belirli modeller için loglama veya yetkilendirme if (params.model === 'User' && params.action === 'delete') { // Yetkilendirme kontrolü yapılabilir console.warn('Kullanıcı silme işlemi denendi!'); } return result; }); async function runMiddlewareExample() { await prisma.user.findMany(); // Bu sorgu middleware tarafından loglanacak await prisma.$disconnect(); } // Kullanım: // runMiddlewareExample(); ``` **4. Çoklu Veritabanı Desteği (Preview Feature)** * **Problem:** Tek bir Prisma projesi içinde birden fazla, farklı veritabanı ile çalışmak istiyoruz (örneğin, birincil veritabanı PostgreSQL, loglar için MongoDB). * **Çözüm:** Prisma'nın 2026 itibarıyla olgunlaşan çoklu veritabanı desteği (multi-schema veya multi-datasource) ile `schema.prisma` dosyanızda birden fazla `datasource` tanımlayabilirsiniz. Bu, mikroservis mimarilerinde veya karmaşık veri depolama ihtiyaçlarında esneklik sağlar. ```prisma // schema.prisma (Çoklu veritabanı örneği) generator client { provider = "prisma-client-js" previewFeatures = ["multiSchema", "postgresqlExtensions"] } datasource mainDb { provider = "postgresql" url = env("DATABASE_URL_MAIN") } datasource analyticsDb { provider = "mongodb" url = env("DATABASE_URL_ANALYTICS") } model User { id Int @id @default(autoincrement()) email String @unique @@datasource(mainDb) } model AnalyticsEvent { id String @id @map("_id") @default(auto()) eventName String timestamp DateTime @default(now()) data Json @@datasource(analyticsDb) } ``` > **Deneyim Notu:** Çoklu veritabanı kullanımı, özellikle büyük ölçekli kurumsal projelerde veri ayrıştırma ve ölçeklenebilirlik açısından büyük avantajlar sunar. Ancak, yönetim karmaşıklığını da artırabilir; bu nedenle dikkatli planlama gerektirir. Bu ileri seviye teknikler, Prisma'nın sadece basit bir ORM olmadığını, aynı zamanda karmaşık ve üretim sınıfı uygulamalar için güçlü bir veritabanı katmanı çözümü sunduğunu göstermektedir. ### BÖLÜM 8 - Best Practices & Anti-Patterns Prisma ile çalışırken performans, güvenlik ve sürdürülebilirlik açısından dikkat etmeniz gereken bazı en iyi uygulamalar ve kaçınmanız gereken anti-pattern'lar bulunmaktadır. Ekibimizde Prisma'ya geçiş sürecinde öğrendiğimiz 3 kritik ders, bu best practice'lerin önemini ortaya koydu. **✅ DOĞRU Uygulamalar:** 1. **Veritabanı Şemasını İyi Tasarlayın:** Prisma'nın gücü, iyi tanımlanmış bir `schema.prisma` dosyasından gelir. İlişkileri doğru kurun, indeksleri gerektiği gibi tanımlayın (`@@index`), benzersiz kısıtlamaları (`@unique`) kullanın. Bu, performans ve veri bütünlüğü için temeldir. 2. **`select` ile Yalnızca İhtiyacınız Olan Veriyi Çekin:** Büyük tablolardan tüm sütunları çekmek yerine, `select` anahtar kelimesini kullanarak sadece ihtiyacınız olan sütunları belirtin. Bu, ağ trafiğini ve veritabanı yükünü azaltarak sorgu performansını artırır. ```typescript // Doğru: Sadece kullanıcı adını ve e-postasını çek const users = await prisma.user.findMany({ select: { name: true, email: true }, }); ``` 3. **İlişkili Veriler İçin `include` Kullanın:** İlişkili verileri ayrı ayrı sorgulamak yerine `include` kullanarak N+1 sorgu problemini önleyin. Prisma, bunu tek bir optimize edilmiş sorguya dönüştürür. ```typescript // Doğru: Kullanıcıları ve postlarını tek sorguda getir const usersWithPosts = await prisma.user.findMany({ include: { posts: true }, }); ``` 4. **Ortam Değişkenlerini Kullanın:** Veritabanı bağlantı URI'si gibi hassas bilgileri `.env` dosyalarında tutun ve bunları versiyon kontrolüne dahil etmeyin. Bu, güvenlik için kritik öneme sahiptir. 5. **Migrasyonları Düzenli Olarak Uygulayın:** `npx prisma migrate dev` ve `npx prisma migrate deploy` komutlarını kullanarak şema değişikliklerinizi düzenli olarak veritabanına uygulayın. Bu, şema ile kod arasındaki uyumsuzlukları önler. 6. **`PrismaClient` Instance'ını Tek Kullanın (Singleton):** Her istekte yeni bir `PrismaClient` örneği oluşturmak yerine, uygulamanız boyunca tek bir örnek kullanın. Bu, veritabanı bağlantı havuzunu daha verimli kullanmanızı sağlar ve kaynak tüketimini azaltır. ```typescript // Doğru: Singleton pattern // utils/prisma.ts import { PrismaClient } from '@prisma/client'; let prisma: PrismaClient; if (process.env.NODE_ENV === 'production') { prisma = new PrismaClient(); } else { if (!global.prisma) { global.prisma = new PrismaClient(); } prisma = global.prisma; } export default prisma; ``` 7. **Hata Yönetimini Ciddiye Alın:** Veritabanı operasyonları her zaman başarısız olabilir. `try...catch` blokları kullanarak hataları yakalayın ve kullanıcıya veya loglara anlamlı mesajlar döndürün. 8. **Veritabanı İndekslerini Kullanın:** Sıkça sorgulanan sütunlara indeks ekleyerek sorgu performansını önemli ölçüde artırın. `schema.prisma` içinde `@@index([columnName])` kullanarak indeks tanımlayabilirsiniz. 9. **Güvenlik Odaklı Geliştirme:** Prisma Client, SQL enjeksiyonunu doğal olarak önlese de, uygulamanıza gelen kullanıcı girdilerini (input validation) her zaman doğrulayın ve sanitize edin. Bu, diğer güvenlik açıklarını (XSS, CSRF) önlemek için önemlidir. **❌ YANLIŞ Uygulamalar (Anti-Patterns):** 1. **Tüm Sütunları Çekmek (`select` kullanmamak):** Özellikle büyük tablolarda, ihtiyacınız olmayan tüm veriyi çekmek performansı düşürür ve gereksiz kaynak tüketimine yol açar. 2. **N+1 Sorgu Problemi (`include` kullanmamak):** İlişkili verileri döngü içinde her seferinde ayrı ayrı sorgulamak, veritabanına çok sayıda gereksiz istek gönderir ve performansı felç eder. 3. **Hassas Bilgileri Hardcode Etmek:** Veritabanı kimlik bilgileri, API anahtarları gibi hassas bilgileri kod içinde doğrudan tutmak büyük bir güvenlik zafiyetidir. 4. **Migrasyonları Atlamak:** Şema değişikliklerini manuel olarak veritabanına uygulamak veya migrasyonları atlamak, şema ile kod arasında uyumsuzluklara yol açar ve üretim ortamında beklenmedik hatalara neden olabilir. 5. **`PrismaClient` Instance'ını Her Yerde Oluşturmak:** Her veritabanı işlemi için yeni bir `PrismaClient` örneği oluşturmak, veritabanı bağlantı havuzunu verimsiz kullanır ve uygulamanızın performansını düşürür. 6. **Girdi Doğrulamasını İhmal Etmek:** Kullanıcıdan gelen verileri doğrulamadan doğrudan veritabanına kaydetmek, veri bütünlüğü sorunlarına ve güvenlik açıklarına yol açabilir. Bu best practice'leri uygulayarak, 2026'nın modern geliştirme standartlarına uygun, güvenli, performanslı ve sürdürülebilir Prisma uygulamaları geliştirebilirsiniz. ### BÖLÜM 9 - Yaygın Hatalar ve Çözümleri (Troubleshooting) Prisma ile çalışırken karşılaşabileceğiniz bazı yaygın hatalar ve bunların çözümleri aşağıda listelenmiştir. Production ortamında Prisma kullanırken karşılaştığım en yaygın sorunlardan biri, migrasyon çakışmaları ve bağlantı sorunlarıydı. 1. **Problem: `PrismaClientInitializationError: Can't reach database server at ...`** * **Sebep:** Prisma Client, belirtilen veritabanına bağlanamıyor. Bu genellikle yanlış `DATABASE_URL` ortam değişkeni, veritabanı sunucusunun çalışmıyor olması, yanlış port veya güvenlik duvarı ayarları nedeniyle oluşur. * **Çözüm:** * `.env` dosyanızdaki `DATABASE_URL`'nin doğru olduğundan emin olun (kullanıcı adı, şifre, host, port, veritabanı adı). * Veritabanı sunucunuzun çalıştığını kontrol edin. * Veritabanı portunun (örneğin P