Gereksinimler ve Ön Hazırlık
Projeye başlamadan önce sisteminizde Node.js (v20 veya üzeri önerilir) ve bir veritabanı yönetim sisteminin (PostgreSQL, MySQL veya SQLite) yüklü olması gerekir. İlk adım olarak projenizi başlatın ve gerekli paketleri yükleyin.
# Proje klasörünü oluşturun
mkdir sequelize-iliskiler
cd sequelize-iliskiler
npm init -y
# Sequelize ve veritabanı sürücüsünü yükleyin
npm install sequelize sequelize-cli pg pg-hstore
Yukarıdaki komutlar, Sequelize kütüphanesini ve PostgreSQL için gerekli olan sürücüyü projenize dahil eder. Eğer MySQL kullanıyorsanız pg pg-hstore yerine mysql2 paketini yüklemelisiniz.
Sequelize Bağlantı Ayarlarını Yapılandırma
Veritabanı bağlantısını yönetmek için bir database.js dosyası oluşturarak Sequelize örneğini başlatmalısınız. Bu dosya, tüm modellerin ortak bir bağlantı havuzunu kullanmasını sağlar.
const { Sequelize } = require('sequelize');
const sequelize = new Sequelize('veritabani_adi', 'kullanici', 'sifre', {
host: 'localhost',
dialect: 'postgres',
logging: false // Konsolda SQL sorgularını gizlemek için
});
module.exports = sequelize;
Bu yapılandırma, uygulamanızın veritabanı ile konuşmasını sağlar. logging: false ayarı, geliştirme aşamasında konsolun temiz kalmasına yardımcı olur, ancak hata ayıklama sırasında console.log olarak değiştirebilirsiniz.
One-to-One (Bire Bir) İlişki Kurulumu
Bire bir ilişki, bir tablodaki tek bir kaydın diğer tablodaki tek bir kayıtla eşleştiği durumlardır. Örneğin, bir "Kullanıcı"nın sadece bir "Profil"e sahip olması durumu.
const User = sequelize.define('User', { name: DataTypes.STRING });
const Profile = sequelize.define('Profile', { bio: DataTypes.TEXT });
// İlişkiyi tanımlama
User.hasOne(Profile);
Profile.belongsTo(User);
hasOne metodu, ana tablonun (User) diğer tabloya (Profile) sahip olduğunu belirtir. belongsTo ise ters yönlü ilişkiyi tanımlayarak veritabanı şemasında yabancı anahtarın (foreign key) oluşturulmasını sağlar.
Many-to-Many (Çoka Çok) İlişki ve Through Tablosu
Çoka çok ilişkilerde, iki tablo arasında köprü görevi gören bir "ara tablo" (junction table) gerekir. Örneğin, "Öğrenciler" ve "Dersler" arasındaki ilişki.
const Student = sequelize.define('Student', { name: DataTypes.STRING });
const Course = sequelize.define('Course', { title: DataTypes.STRING });
// Ara tabloyu tanımlama
const Enrollment = sequelize.define('Enrollment', {});
Student.belongsToMany(Course, { through: Enrollment });
Course.belongsToMany(Student, { through: Enrollment });
belongsToMany metodu, Sequelize'in otomatik olarak bir ara tablo oluşturmasını sağlar. through parametresi, bu ara tablonun adını veya modelini belirler.
İlişkisel Verileri Sorgulama (Eager Loading)
İlişkili verileri tek bir sorguda çekmek için Sequelize'in include özelliğini kullanırız. Bu, "N+1" sorgu problemini engeller ve performansı artırır.
const usersWithProfiles = await User.findAll({
include: Profile
});
console.log(JSON.stringify(usersWithProfiles, null, 2));
Bu kod bloğu, tüm kullanıcıları ve onlara bağlı olan profil bilgilerini tek bir SQL JOIN sorgusu ile getirir. Bu yöntem, veritabanı trafiğini ciddi oranda düşürür.
İlişki Türleri Karşılaştırması
| İlişki Türü | Sequelize Metodu | Kullanım Senaryosu |
|---|---|---|
| One-to-One | hasOne / belongsTo | Kullanıcı - Profil |
| One-to-Many | hasMany / belongsTo | Yazar - Makale |
| Many-to-Many | belongsToMany | Öğrenci - Ders |
Güvenlik Uyarısı: Veritabanı işlemlerinde asla kullanıcıdan gelen veriyi doğrudan sorguya dahil etmeyin. Sequelize, SQL Injection saldırılarına karşı korumalıdır; ancak her zaman model validasyonlarını ve tip kontrollerini kullanın. Üretim ortamında
sequelize.sync({ force: true })komutunu asla kullanmayın, aksi takdirde tüm verileriniz silinebilir.
Sıkça Sorulan Sorular
Sequelize'de N+1 problemi nedir?
N+1 problemi, her bir ana kayıt için ilişkili verileri ayrı ayrı sorguladığınızda oluşur. Sequelize'de include kullanarak bu durumu tek bir JOIN sorgusuna indirgeriz.
Yabancı anahtar (Foreign Key) ismini nasıl değiştirebilirim?
İlişki tanımlarken { foreignKey: 'istenen_isim' } seçeneğini kullanarak veritabanındaki sütun ismini özelleştirebilirsiniz.
İlişkili veriyi silerken nelere dikkat etmeliyim?
onDelete: 'CASCADE' seçeneğini kullanarak, ana kayıt silindiğinde ilişkili kayıtların da otomatik olarak silinmesini sağlayabilirsiniz.
Many-to-Many ilişkisinde ara tabloya nasıl veri eklerim?
Ara tabloya veri eklemek için Sequelize'in oluşturduğu addCourse veya setCourses gibi "mixin" metodlarını kullanabilirsiniz.
Sequelize ile işlem (Transaction) yönetimi nasıl yapılır?
İlişkili kayıtları tek bir atomik işlemde kaydetmek için sequelize.transaction() metodunu kullanarak tüm adımların başarılı olmasını garanti altına alabilirsiniz.
Sequelize ile İlişkisel Veritabanı Performans İpuçları
İlişkisel veritabanlarında karmaşık sorgular oluştururken, özellikle include metodunu yoğun kullandığınızda veritabanı performansınız ciddi şekilde etkilenebilir. Sequelize, geliştirici dostu bir arayüz sunsa da, arka planda oluşturulan SQL sorgularının verimliliğini takip etmek kritiktir.
İndeksleme Stratejileri
İlişkilerde kullanılan yabancı anahtarlar (Foreign Keys) üzerinde indeks oluşturmamak, büyük veri setlerinde tam tablo taramasına (Full Table Scan) neden olur. Sequelize model tanımlamalarınızda indexes özelliğini kullanarak sorgu hızınızı optimize edebilirsiniz.
const User = sequelize.define('User', {
username: DataTypes.STRING
}, {
indexes: [
{
unique: true,
fields: ['username']
}
]
});
Attributes Kısıtlaması (Projection)
İlişkili verileri çekerken sadece ihtiyacınız olan kolonları seçmek, ağ trafiğini ve bellek kullanımını azaltır. Tüm nesneyi çekmek yerine attributes parametresini kullanın.
const users = await User.findAll({
include: [{
model: Profile,
attributes: ['bio', 'avatarUrl'] // Sadece gerekli alanlar
}]
});
İlişkisel Veri Yapılarında Hata Ayıklama (Debugging)
Sequelize ile çalışırken en sık karşılaşılan sorunlar, yanlış yapılandırılmış ilişki tanımları veya döngüsel bağımlılıklardır. Hangi SQL sorgusunun çalıştırıldığını görmek, hataları tespit etmenin en hızlı yoludur.
SQL Sorgularını İzleme
Geliştirme aşamasında Sequelize'in ürettiği SQL sorgularını konsolda görmek için logging parametresini aktif edin. Bu sayede include yapısının beklediğiniz LEFT OUTER JOIN veya INNER JOIN işlemini yapıp yapmadığını doğrulayabilirsiniz.
const sequelize = new Sequelize('database', 'user', 'pass', {
host: 'localhost',
dialect: 'postgres',
logging: (msg) => console.log('SQL Sorgusu: ', msg) // Sorguları izle
});
Eager Loading Hatalarını Giderme
Eğer Eager Loading sırasında "Association not found" hatası alıyorsanız, model tanımlarınızdaki as (alias) isimlendirmelerinin hem ilişki tanımında hem de sorgu aşamasında aynı olduğundan emin olun. Sequelize, alias kullanıldığında sorgu içerisinde bu takma ismi zorunlu tutar.
// Tanımlama
User.hasMany(Post, { as: 'posts' });
// Sorgulama
const user = await User.findOne({
include: [{
model: Post,
as: 'posts' // Alias eşleşmesi kritik
}]
});
Bu hata ayıklama yöntemleri, karmaşık ilişkisel yapılarda geliştirme sürecinizi hızlandıracak ve çalışma zamanı hatalarını minimize edecektir.
Sonuç
Node.js ve Sequelize kullanarak veritabanı ilişkilerini yönetmek, başlangıçta karmaşık görünse de, doğru metodolojilerle oldukça düzenli bir süreçtir. Bu rehberde öğrendiğiniz hasOne, hasMany ve belongsToMany yapıları, orta ve büyük ölçekli projelerinizin temelini oluşturacaktır. Bir sonraki adım olarak, Sequelize Migrations (göçler) konusunu araştırarak veritabanı şemanızı versiyon kontrolü altında nasıl yöneteceğinizi öğrenebilirsiniz.
Not: Bu makaledeki kod örnekleri eğitim amaçlıdır. Üretim ortamına geçmeden önce veritabanı bağlantı bilgilerini environment (çevre) değişkenlerinde saklamayı ve güvenlik duvarı ayarlarınızı yapılandırmayı unutmayın.


Yorumlar (0)
Yorum Yaz