emirhanHCL 1
emirhanHCL
farkmt2official 1
farkmt2official
mannaxxx 1
mannaxxx
kralhakan2009 1
kralhakan2009
Vahsi Uzman 1
Vahsi Uzman
Best Studio 1
Best Studio
TuZaKK 1
TuZaKK
Mt2Hizmet 1
Mt2Hizmet
Hikaye Ekle

[NODE JS] Sequelize ORM ile Veritabanı İşlemleri

  • Konuyu başlatan Konuyu başlatan Silverhand
  • Başlangıç tarihi Başlangıç tarihi
  • Cevaplar Cevaplar 1
  • Görüntüleme Görüntüleme 13

Türkiye'de ilk Mobil & PC Aynı Anda Metin2 Oyna. Triarchonline kalıcı ve uzun ömürlü yapısı ile 24 Temmuz'da açılıyor. | 1-99 Mobil Metin2 Triarch HEMEN TIKLA!

nodejs.png


[NODE JS] Sequelize ORM ile Veritabanı İşlemleri​


ORM (Object-Relational Mapping) kavramıyla ilk tanıştığımda, veritabanı ile uygulama arasındaki köprünün ne kadar zarif olabileceğini anlamıştım. Sequelize, Node.js ekosistemindeki en olgun ve yaygın kullanılan ORM kütüphanesidir. PostgreSQL, MySQL, MariaDB, SQLite ve Microsoft SQL Server gibi farklı veritabanlarını destekler. Bu çoklu destek, projenizin büyümesiyle veritabanı değişikliği yapmanız gerektiğinde hayat kurtarıcı olabilir.

Sequelize'ın en büyük avantajı, ham SQL yazmadan veritabanı işlemlerini JavaScript nesneleri ve metodlarıyla gerçekleştirebilmemiz. Model tanımları, ilişkiler, sorgular, doğrulamalar — hepsini JavaScript koduyla ifade ederiz. Bu yaklaşım, özellikle SQL'e çok aşina olmayan geliştiriciler için büyük kolaylık sağlar. Ancak karmaşık sorgularda ham SQL'e dönmek gerekebilir ve Sequelize buna da olanak tanır.

Model tanımlama, Sequelize'ın temelini oluşturur. Her model, veritabanındaki bir tabloya karşılık gelir. Model alanlarının türlerini, doğrulama kurallarını, varsayılan değerlerini ve diğer özelliklerini tanımlarız. DataTypes modülü, STRING, INTEGER, FLOAT, BOOLEAN, DATE, JSON, ENUM gibi birçok veri türünü destekler.

Doğrulama (validation) konusunda Sequelize çok güçlü. Her alan için birden fazla doğrulama kuralı tanımlayabiliriz: isEmail, isURL, isNumeric, len, min, max gibi yerleşik doğrulayıcılar mevcuttur. Ayrıca özel doğrulayıcı fonksiyonlar da yazabiliriz. Bu doğrulamalar, verinin veritabanına kaydedilmeden önce kontrol edilmesini sağlar.

Hook'lar (yaşam döngüsü kancaları), Sequelize'ın güçlü özelliklerinden biridir. beforeCreate, afterCreate, beforeUpdate, afterUpdate gibi kancalar, model işlemleri öncesinde veya sonrasında ek mantık eklememize olanak tanır. Örneğin, kullanıcı oluşturulmadan önce şifreyi hashlemek veya bir kayıt silindikten sonra ilgili dosyaları temizlemek gibi işlemler hook'larla yapılabilir.

Scope'lar, sık kullanılan sorgu filtrelerini tanımlamamıza yarar. Varsayılan scope ve adlandırılmış scope'lar kullanarak kod tekrarını azaltabiliriz. Örneğin, sadece aktif kayıtları getiren bir scope tanımlayıp tüm sorgularda kullanabiliriz.

JavaScript:
// Sequelize ORM ile Veritabanı İşlemleri
const { Sequelize, DataTypes, Op, Model } = require('sequelize');

// Veritabanı bağlantısı
const sequelize = new Sequelize('egitim_db', 'kullanici', 'sifre', {
  host: 'localhost',
  dialect: 'postgres', // veya 'mysql', 'sqlite', 'mssql'
  logging: (msg) => console.log(`[SQL] ${msg}`),
  pool: {
    max: 5,
    min: 0,
    acquire: 30000,
    idle: 10000
  },
  define: {
    timestamps: true,       // createdAt ve updatedAt otomatik
    underscored: true,      // snake_case sütun isimleri
    freezeTableName: true   // Tablo ismini çoğullaştırma
  }
});

// Kullanıcı Modeli
class Kullanici extends Model {
  // Örnek metod
  tamIsim() {
    return `${this.ad} ${this.soyad}`;
  }

  // Sınıf metodu
  static async aktifKullanicilariGetir() {
    return await this.scope('aktif').findAll();
  }
}

Kullanici.init({
  ad: {
    type: DataTypes.STRING(50),
    allowNull: false,
    validate: {
      notEmpty: { msg: 'İsim boş olamaz' },
      len: { args: [2, 50], msg: 'İsim 2-50 karakter arasında olmalıdır' }
    }
  },
  soyad: {
    type: DataTypes.STRING(50),
    allowNull: false,
    validate: {
      notEmpty: { msg: 'Soyad boş olamaz' }
    }
  },
  email: {
    type: DataTypes.STRING,
    allowNull: false,
    unique: { msg: 'Bu e-posta adresi zaten kayıtlı' },
    validate: {
      isEmail: { msg: 'Geçerli bir e-posta adresi giriniz' }
    }
  },
  sifre: {
    type: DataTypes.STRING,
    allowNull: false,
    validate: {
      len: { args: [8, 100], msg: 'Şifre en az 8 karakter olmalıdır' }
    }
  },
  telefon: {
    type: DataTypes.STRING(15),
    validate: {
      is: { args: /^[0-9+\-\s]+$/, msg: 'Geçerli bir telefon numarası giriniz' }
    }
  },
  dogumTarihi: {
    type: DataTypes.DATEONLY,
    validate: {
      isDate: { msg: 'Geçerli bir tarih giriniz' },
      isBefore: {
        args: new Date().toISOString().split('T')[0],
        msg: 'Doğum tarihi bugünden önce olmalıdır'
      }
    }
  },
  rol: {
    type: DataTypes.ENUM('kullanici', 'moderator', 'admin'),
    defaultValue: 'kullanici'
  },
  aktif: {
    type: DataTypes.BOOLEAN,
    defaultValue: true
  },
  sonGirisTarihi: {
    type: DataTypes.DATE
  }
}, {
  sequelize,
  modelName: 'Kullanici',
  tableName: 'kullanicilar',
  // Scope tanımları
  scopes: {
    aktif: { where: { aktif: true } },
    adminler: { where: { rol: 'admin' } },
    sonKayitlar: {
      order: [['created_at', 'DESC']],
      limit: 10
    }
  },
  // Hook tanımları
  hooks: {
    beforeCreate: async (kullanici) => {
      // Şifre hashleme simülasyonu
      console.log(`Şifre hashleniyor: ${kullanici.ad}`);
      // Gerçek uygulamada: kullanici.sifre = await bcrypt.hash(kullanici.sifre, 12);
    },
    afterCreate: (kullanici) => {
      console.log(`Yeni kullanıcı oluşturuldu: ${kullanici.tamIsim()}`);
    }
  }
});

// Gönderi Modeli
class Gonderi extends Model {}

Gonderi.init({
  baslik: {
    type: DataTypes.STRING(200),
    allowNull: false,
    validate: {
      notEmpty: true,
      len: [5, 200]
    }
  },
  icerik: {
    type: DataTypes.TEXT,
    allowNull: false
  },
  durum: {
    type: DataTypes.ENUM('taslak', 'yayinda', 'arsivlendi'),
    defaultValue: 'taslak'
  },
  goruntulemeSayisi: {
    type: DataTypes.INTEGER,
    defaultValue: 0
  },
  etiketler: {
    type: DataTypes.JSON,
    defaultValue: []
  },
  yayinTarihi: {
    type: DataTypes.DATE
  }
}, {
  sequelize,
  modelName: 'Gonderi',
  tableName: 'gonderiler'
});

// Yorum Modeli
class Yorum extends Model {}

Yorum.init({
  icerik: {
    type: DataTypes.TEXT,
    allowNull: false,
    validate: {
      len: [1, 1000]
    }
  },
  onaylandi: {
    type: DataTypes.BOOLEAN,
    defaultValue: false
  }
}, {
  sequelize,
  modelName: 'Yorum',
  tableName: 'yorumlar'
});

// İlişki tanımları
Kullanici.hasMany(Gonderi, { foreignKey: 'yazarId', as: 'gonderiler' });
Gonderi.belongsTo(Kullanici, { foreignKey: 'yazarId', as: 'yazar' });

Gonderi.hasMany(Yorum, { foreignKey: 'gonderiId', as: 'yorumlar' });
Yorum.belongsTo(Gonderi, { foreignKey: 'gonderiId' });

Kullanici.hasMany(Yorum, { foreignKey: 'yazarId', as: 'yorumlarim' });
Yorum.belongsTo(Kullanici, { foreignKey: 'yazarId', as: 'yorumYazari' });

// CRUD İşlemleri
async function crudIslemleri() {
  // Tabloları senkronize et
  await sequelize.sync({ force: true });

  // CREATE - Oluşturma
  const kullanici1 = await Kullanici.create({
    ad: 'Emre',
    soyad: 'Yılmaz',
    email: 'emre@ornek.com',
    sifre: 'guvenli_sifre_123',
    telefon: '+90 555 123 4567',
    dogumTarihi: '1995-03-15',
    rol: 'admin'
  });
  console.log('Kullanıcı oluşturuldu:', kullanici1.tamIsim());

  // Toplu oluşturma
  const kullanicilar = await Kullanici.bulkCreate([
    { ad: 'Selin', soyad: 'Kaya', email: 'selin@ornek.com', sifre: 'sifre12345' },
    { ad: 'Can', soyad: 'Demir', email: 'can@ornek.com', sifre: 'sifre12345' },
    { ad: 'Deniz', soyad: 'Öztürk', email: 'deniz@ornek.com', sifre: 'sifre12345' }
  ], { validate: true });
  console.log(`${kullanicilar.length} kullanıcı toplu oluşturuldu`);

  // Gönderi oluşturma
  const gonderi = await Gonderi.create({
    baslik: 'Node.js ile Veritabanı İşlemleri',
    icerik: 'Sequelize ORM kullanarak veritabanı işlemleri...',
    yazarId: kullanici1.id,
    durum: 'yayinda',
    etiketler: ['nodejs', 'sequelize', 'veritabanı'],
    yayinTarihi: new Date()
  });

  // READ - Okuma
  const tumKullanicilar = await Kullanici.findAll({
    where: { aktif: true },
    attributes: ['id', 'ad', 'soyad', 'email', 'rol'],
    order: [['ad', 'ASC']]
  });
  console.log('Aktif kullanıcılar:', tumKullanicilar.length);

  // İlişkili veriyle sorgulama
  const gonderiDetay = await Gonderi.findOne({
    where: { id: gonderi.id },
    include: [
      { model: Kullanici, as: 'yazar', attributes: ['ad', 'soyad'] },
      { model: Yorum, as: 'yorumlar', include: [
        { model: Kullanici, as: 'yorumYazari', attributes: ['ad'] }
      ]}
    ]
  });
  console.log('Gönderi:', gonderiDetay.baslik, '- Yazar:', gonderiDetay.yazar.ad);

  // Operatörlerle filtreleme
  const filtrelenmis = await Kullanici.findAll({
    where: {
      [Op.or]: [
        { rol: 'admin' },
        { ad: { [Op.like]: '%e%' } }
      ],
      aktif: true
    }
  });
  console.log('Filtrelenmiş kullanıcılar:', filtrelenmis.length);

  // UPDATE - Güncelleme
  await kullanici1.update({ sonGirisTarihi: new Date() });
  console.log('Giriş tarihi güncellendi');

  await Kullanici.update(
    { aktif: false },
    { where: { sonGirisTarihi: { [Op.lt]: new Date('2025-01-01') } } }
  );

  // DELETE - Silme
  await Yorum.destroy({ where: { onaylandi: false } });
  console.log('Onaylanmamış yorumlar silindi');
}

// Transaction ile güvenli işlem
async function guvenliIslem() {
  const t = await sequelize.transaction();
  try {
    const kullanici = await Kullanici.findOne({
      where: { email: 'emre@ornek.com' },
      transaction: t
    });

    const yeniGonderi = await Gonderi.create({
      baslik: 'Transaction Örneği',
      icerik: 'Bu gönderi transaction içinde oluşturuldu',
      yazarId: kullanici.id,
      durum: 'yayinda'
    }, { transaction: t });

    await t.commit();
    console.log('Transaction başarılı');
  } catch (hata) {
    await t.rollback();
    console.error('Transaction geri alındı:', hata.message);
  }
}

// Ana fonksiyon
async function main() {
  try {
    await sequelize.authenticate();
    console.log('Veritabanı bağlantısı başarılı');
    await crudIslemleri();
    await guvenliIslem();
  } catch (hata) {
    console.error('Hata:', hata.message);
  } finally {
    await sequelize.close();
  }
}

main();

Sequelize ORM, Node.js projelerinde veritabanı işlemlerini büyük ölçüde kolaylaştıran güçlü bir araçtır. Model tanımları, doğrulamalar, ilişkiler ve hook'lar gibi özellikleriyle profesyonel uygulamalar geliştirmek için gereken her şeyi sunar. Başlangıçta öğrenme eğrisi biraz dik olabilir ama bir kez kavradığınızda geliştirme hızınız ciddi şekilde artacaktır.
 

Şu an konuyu görüntüleyenler (Toplam : 0, Üye: 0, Misafir: 0)

Geri
Üst