ORM (Nesne-İlişkisel Eşleme) Nedir?
Kısa tanım
ORM (Object-Relational Mapping), uygulama kodundaki sınıf ve nesneleri ilişkisel veritabanındaki tablo ve satırlarla eşleyen yazılım katmanıdır. Geliştirici SQL yazmak yerine programlama dilinin kendi yapılarıyla veri okur ve yazar; ORM bu işlemleri SQL sorgularına çevirir. Hibernate, Entity Framework Core, Django ORM, SQLAlchemy ve Prisma yaygın örneklerdir. Geliştirme hızı kazandırır, ama ürettiği sorgular izlenmezse N+1 gibi performans sorunlarına yol açabilir.
Diğer adları: Object-Relational Mapping, nesne ilişkisel eşleme, ORM kütüphanesi, object-relational mapper

Nesneler ile tablolar arasındaki uyumsuzluk
Uygulama kodu veriyi nesneler, nesnelerin birbirine referansları, listeler ve kalıtım üzerinden düşünür. İlişkisel veritabanı ise satırlar, sütunlar ve yabancı anahtarlarla çalışır. İki dünya arasındaki bu farka “object-relational impedance mismatch” denir. ORM bu boşluğu kapatır: sınıfları tablolara, alanları sütunlara, nesneler arası ilişkileri join'lere eşler; hangi nesnenin değiştiğini izler ve kaydetme anında gereken INSERT ve UPDATE komutlarını üretir.
İki yaygın tasarım vardır. Active Record deseninde nesne kendini kaydetmeyi bilir (user.save()); Rails ve Laravel'in Eloquent'i bu yaklaşımı kullanır. Data Mapper deseninde ise nesneler veritabanından habersizdir, kaydetme işini ayrı bir katman yapar; Hibernate, Entity Framework Core ve SQLAlchemy bu tarafa yakındır. TypeScript ekosisteminde Prisma, Drizzle ve TypeORM gibi araçlar sorgu sonuçlarını TypeScript tipleriyle eşleyerek derleme zamanında hata yakalamayı kolaylaştırır.
Ne kazandırır?
- Hız ve okunabilirlik: Sık yapılan okuma ve yazmalar birkaç satırla yazılır, tekrar eden eşleme kodu ortadan kalkar.
- Varsayılan güvenlik: ORM'ler değerleri parametre olarak gönderir; bu, SQL enjeksiyonu riskini büyük ölçüde azaltır. Ham SQL kaçış kapıları (raw query) kullanıldığında aynı dikkat yine geliştiriciye düşer.
- Şema yönetimi: Çoğu ORM, model tanımlarından veritabanı migrasyonları üreten araçlarla birlikte gelir.
- Taşınabilirlik: Basit sorgular farklı veritabanlarında aynı kodla çalışır; ancak veritabanına özgü özellikler kullanıldığında bu avantaj hızla azalır.
N+1 sorgu problemi
ORM'lerin en bilinen tuzağı, ilişkili verinin tembel yükleme (lazy loading) ile, döngü içinde tek tek çekilmesidir. Örnek kod genel bir ORM sözdizimiyle yazılmıştır:
// 1 sorgu: son 50 sipariş
const orders = await db.order.findMany({ take: 50 });
for (const order of orders) {
// Her sipariş için ayrı bir sorgu: toplam 1 + 50
const customer = await db.customer.findUnique({ where: { id: order.customerId } });
console.log(order.id, customer.name);
}
// Çözüm: ilişkiyi baştan birlikte yüklemek (eager loading)
const ordersWithCustomer = await db.order.findMany({
take: 50,
include: { customer: true }, // 1 veya 2 sorgu
});Geliştirme ortamında 10 kayıtla fark edilmeyen bu desen, üretimde sayfa başına yüzlerce sorguya ve gözle görülür gecikmeye dönüşür. Şablon içinde order.customer.name gibi masum görünen bir erişim, arka planda sorgu tetikleyebildiği için sorun koda bakınca her zaman görünmez. Tespit için geliştirme ortamında SQL günlüğünü açmak ve istek başına sorgu sayısını izlemek en etkili yöntemdir.
Bedeli ve sınırları
- Sızan soyutlama: ORM SQL'i gizler ama ortadan kaldırmaz. Yavaş bir sayfayı düzeltmek için üretilen sorguyu okumak, planına bakmak ve doğru indeksi eklemek gerekir; bu da SQL bilgisi ister.
- Verimsiz varsayılanlar: Gereksiz tüm sütunları çekmek, toplu güncellemeleri satır satır yapmak ve gereğinden geniş join'ler sık görülür.
- Karmaşık sorgular: Raporlar, pencere fonksiyonları, CTE'ler ve veritabanına özgü operatörler ORM'nin sorgu API'siyle zorlama hâle gelir. Bu noktada parametreli ham SQL ya da bir sorgu oluşturucu (query builder) daha açık ve daha hızlıdır.
- Gizli işlem sınırları: Hangi işlemlerin aynı veritabanı işlemi içinde çalıştığı ORM yapılandırmasına göre değişir ve açıkça bilinmelidir.
Sağlıklı bir denge genellikle şöyledir: rutin okuma ve yazmalarda ORM, performansın kritik olduğu ve sorgunun karmaşıklaştığı yerlerde açıkça yazılmış SQL. Hangisi kullanılırsa kullanılsın, üretilen sorgular görünür olmalıdır.

