Node.JS

Node.JS Sequelize Tablolar Arası İlişki Kurma

Herkese merhaba, Node.JS ile Sequelize yazılarımıza kaldığımız yerden devam ediyoruz. Bu dersimizde Sequelize ile veritabanı tabloları arasında ilişki kurmayı anlatacağım. Hadi başlayalım !

Sequelize ile veritabanı bağlantısı oluşturmayı şu yazımızda anlatmıştım. O yüzden Sequelize ile veritabanı ve tablo oluşturmayı anlatmayacağım, doğrudan ilişki kurmaya geçelim.

İlk olarak bir tane Node.JS projesi oluşturmamız gerekiyor, bunun için proje oluşturmak istediğiniz dizine terminal (Windows için CMD) ile geçerek

npm init --yes

komutunu çalıştıralım. Tabi projeye Sequelize modülünü eklememizde gerekiyor. Bunun için yine terminalden

npm i sequelize

komutunu çalıştıralım ve Npm’in modülü indirip projeye eklemesini bekleyelim. Modül projeye eklendikten sonra veritabanı modelini oluşturmak için bir tane models adında klasör oluşturalım. Veritabanı olarak Sequelize ile veritabanı bağlantısı yaptığımız yazımızda kullandığımız veritabanını kullanacağız fakat o yapıyı biraz değiştirerek kitaplar tablosunda bulunan yazarAdi sütununu kaldırıp yerine integer tipte yazarID sütununu ekleyecek ve yazarlar içinde bir tablo oluşturacağız. yazarlar tablosunda ise int tipte primary key ve auto increment olan yazarID, varchar tipte ve 255 karakterle sınırlı yazarAdi sütunlarını ekleyeceğiz. Yani sonuç olarak kullanicilar, kitaplar ve yazarlar olmak üzere 3 farklı tablomuz olacak. kullanicilar tablosunda primary key ve auto increment olan integer tipte kullaniciID, varchar tipte 255 karakterli kullaniciAdi ve varchar tipte 255 karakterli sifre tabloları olacak. yazarlar tablosunda integer tipte auto increment ve primary key olan yazarID ve varchar tipte 255 karakterli yazarAdi sütunları olacak. Son olarak kitaplar tablosunda ise integer tipte primary key ve auto increment olan kitapID, varchar tipte 20 karakterli isbn ve integer tipte yazarID sütunları olacak. yazarlar ve kitaplar tablosu ilişkili olacak ve ilişki yazarID sütunları üzerinden yapılacak.

Öncelikle kullanicilar tablosunu hazırlayalım. Bunun için oluşturduğumuz models klasörü içine bir tane kullanicilar.js adında dosya oluşturup açalım ve şu kodları yazalım;

const { sequelize, DataTypes } = require('sequelize');
module.exports = {
    kullanicilar: () => {
        const kullanici = sequelize.define('kullanicilar', {
            kullaniciID: {
                type: DataTypes.INTEGER,
                primaryKey: true
            },
            kullaniciAdi: {
                type: DataTypes.STRING(255)
            },
            sifre: {
                type: DataTypes.STRING(255)
            }
        });
        return kullanici;
    }
}

kullanicilar tablosu modelini oluşturduk, sıra geldi yazarlar ve kitaplar tablolarına. Bu iki tablo birbiriyle ilişkili olduğu için biraz farklı yapacağız. Aslında modeli oluşturma tıpkı kullanicilar tablosunda olduğu gibi olacak ama ilişkiyi de belirtmemiz gerekecek. Sequelize ile ilişki oluşturmak için belongsTo, hasMany ve hasOne adında üç farklı fonksiyon kullanılıyor. hasMany ile birden çoka (1-n yada n-1) yada çoktan çoka(n-n), hasOne ve belongsTo ilede birden bire (1-1) ilişki kuruluyor. Birden bire, birden çoka ve çoktan çoka diye 3 farklı şey dedim ama gelin bunların ne olduğunu kısaca açıklayalım.

Birden bire bağlantı, bir tablonun bir sütunu farklı bir tablonun bir sütununa bir tane bağlantı yapacaksa yani örneğin bir kitabın bir yazarı ve bir yazarın da bir kitabı olacaksa kullanılmakta.

Birden çoka bağlantı, bir tablonun bir sütunu farklı bir tablonun bir sütununa birden fazla bağlantı yapacaksa, yani örneğin bir kitabın birden fazla yazarı olacak yada bir yazarın birden çok kitabı olacaksa kullanılmakta.

Çoktan çoka bağlantı, bir tablonun bir sütunu farklı bir tablonun bir sütununa karşılıklı olarak birden fazla bağlantı yapılacaksa, yani örneğin bir yazarın birden çok kitabı olacak ve bir kitabın birden çok yazarı olacaksa kullanılmakta.

Sequelize ile tablolar arası ilişki oluşturmak birden bire ilişkiler için ilişkili olacak tabloların bir tanesinde ilişkiyi belirtmek gerekiyor, birden çoka ve çoktan çoka bağlantılar içinde her iki tabloda da ilişkiyi oluşturmamız gerek. Bizim veritabanımızda birden bire bağlantı olacak (bir kitabın bir yazarı, bir yazarın bir kitabı olabilecek), bu yüzden hem tabloların birinde ilişkiyi oluşturmamız yeterli olacaktır. Biz yazarlar tablosunda oluşturalım (kitaplar tablosunda da oluşturulabilir, bu tamamen size kalmış fakat ben örnek olması açısından yazarlar tablosunda oluşturacağım). Bu anlattıklarıma göre önce yazarlar tablosunu oluşturalım. Bunun için models klasörü altında yazarlar.js adında dosya oluşturup içine şu kodları yazalım;

const { sequelize, DataTypes } = require('sequelize');
module.exports = {
    yazarlar: () => {
        const yazar = sequelize.define('yazarlar', {
            yazarID: {
                type: DataTypes.INTEGER,
                primaryKey: true
            },
            yazarAdi: {
                type: DataTypes.STRING(255)
            }
        },
            {
                indexes: [{
                    unique: true,
                    fields: ['yazarID', 'yazarId'],
                    where: { deletedAt: null }
                }],
            }
    timestamps: true,
            paranoid: true
        );
        yazar.associate = models => {
            yazar.belongsTo(models.kitaplar, {
                as: 'kitaplar',
                foreignKey: { allowNull: false }
            });
        }
        return yazarlar;
    }
}

Evet kitaplar tablosunu oluşturduk. indexes dizisi ile indexleri oluşturduk ve fields değeriyle yazarlar tablosundaki yazarID ile aşağıda ilişki oluşturduğumuz tabloda (yani kitaplar tablosu) bulunan yazarId sütunlarının ilişkili olacağını belirttik. Ardından associate adındaki bir fonksiyon ile ilişki oluşturacağımızı belirttik. Ardından yazar.belongsTo(models.kitaplar) ile models klasörü altındaki kitaplar dosyası yani modeli ile birden bire ilişki olacağını söyledik. Son olarak foreign key oluşturarak ilişkiyi tamamladık ve bu ilişkinin adını (as: kitaplar değeri ile) kitaplar olarak belirttik.

Şimdide kitaplar tablosunu oluşturalım. Bunun için models klasörü altında bir tane kitaplar.js dosyası oluşturup içine şu kodları yazalım;

const { sequelize, DataTypes } = require('sequelize');
module.exports = {
    kitaplar: () => {
        const kitap = sequelize.define('kitap', {
            kitapID: {
                type: DataTypes.INTEGER,
                primaryKey: true
            },
            kitapAdi: { type: DataTypes.STRING(255), },
            isbn: { type: DataTypes.STRING(20) },
            yazarId: { type: DataTypes.INTEGER }
        });
        return kitap;
    }
}

Evet veritabanında bulunan tabloların modellerini Sequelize ile oluşturduk. Şimdi sıra geldi Sequelize nesnesini oluşturma ve modelleri doldurmaya. Bunun için models klasörü altında index.js adında bir tane dosya oluşturup açalım. Burada az önce oluşturduğumuz kitaplar, yazarlar ve kullanicilar modellerini oluşturduğumuz bir obje içine dolduracağız ve bu objecti geriye döndürerek dışarıdan kullanılabilir hale getireceğiz. Ayrıca birde yeni bir Sequelize nesnesi oluşturarak veritabanına bağlantı yapacağız. Bu bağlantı ile Sequelize veritabanına bağlantı yapacak ve bizim veritabanı işlemleri yapabilmemize olanak sağlayacak. Veritabanı modellerini, models klasörü altında bulunan dosyaları içeri aktararak (require ederek) bulacağız. Tabi her modeli elle yapmayacak, models klasöründeki dosyaları bulup foreach döngüsü ile dönecek ve her döngüde ilgili dosyayı modele doldurma işlemi yapacağız. Klasör içerisinde bulunan dosyaları bulmak için fs, dosya yollarını işletim sistemine uygun hale getirmek için path modülünü kullanacağız. Bu modüller Node.JS kurulumu ile beraber geldiği için kurmamıza gerek yok, doğrudan kullanabiliriz ama sayfada çağırmamız gerekecek tabiki.

Son olarak modeller arasındaki ilişkileri tıpkı yazarlar modelinde yaptığımız gibi associate fonksiyonunu kullanarak Sequelize’a bildireceğiz. Bu kadar bilgiden sonra artık kodları yazalım.

const sequelize = require('sequelize');
const path = require('path');
const fs = require('fs');
const database = {};
function models() {
    let sequelize = new sequelize({
        host: 'localhost',
        port: 3306,
        user: 'root',
        password: '',
        database: 'kutuphane',
        dialect: 'mysql',
        define: { freezeTableName: true }
    });
    fs.readdirSync(__dirname).forEach(file => {
        const model = require(path.join(__dirname, file));
        database[model.name] = model;
    });
    Object.keys(database).forEach(modelName => {
        if (database[modelName].associate)
            database[modelName].associate(database);
    });
    database.sequelize = sequelize;
    database.Sequelize = Sequelize;
    return database;
}
exports.models = models;

Evet Sequelize modelimizi ve tablolarımızı da bu şekilde oluşturduk fakat Sequelize nesnesi oluştururken dialect adında bir obje gönderdik. O ne derseniz, Sequelize; Mysql, Mssql, MongoDB gibi birçok veritabanı çeşidi ile bağlantı kurabiliyor ve kullanabiliyoruz. dialect objesi ile bağlantı yapmak istediğimiz veritabanı tipini belirtiyoruz. Yani dialect olarak mysql gönderdiğimizde ‘bak ben Mysql bilgileri gönderdim, sende Mysql’e göre işlem yapacaksın’ demiş oluyoruz. Ayrıca normalde Sequelize, diğer birçok ORM’de olduğu gibi tablo isimlerinin sonuna s takısı ekliyor. Yani biz kullanicilar ve kitaplar diye iki tablo oluşturduk ama Sequelize bu tabloları oluştururken kullanicilars ve kitaplars isimleriyle oluşturacaktı. define özelliği ve onun içindeki freezeTableName özelliğini true yaparak tablo isimlerine eklenecek olan s takılarını kaldırıyoruz. Yani bizim tablolarımız kullanicilar ve kitaplar adıyla oluşturulacaktır.

Sequelize modelimizi oluşturup, tablolarımızı içine eklediğimize göre artık bağlantıyı yapabilir ve veritabanını oluşturabiliriz. Veritabanı bağlantısı yapabilmek için örneğin connection.js adında bir dosya oluşturalım ve az önce Sequelize modelini oluşturduğumuz models klasörü altındaki index.js dosyasını çağıralım. Yani sayfanın başına

const models = require('./models');

kod satırını yazalım. Sequelize ile veritabanını oluşturmak için model içerisinde bulunan sequelize özelliğinin sync() metodunu çağırmamız gerekiyor. Adının açılımından da (synchronize) anlaşılacağı üzere bu metod veritabanını senkronize ediyor ve veritabanı ve tabloları yoksa oluşturuyor. Ayrıca bu metod bize Promise döndürdüğü için oluşabilecek hatalarıda yakalayabiliyoruz. Kullanımı da şöyle olsun;

models().sequelize.sync().then(() => {
    console.log('Veritabanı oluşturuldu ve bağlantı sağlandı.')
}).catch(error => {
    console.error(error);
});

Evet şimdi veritabanı tarafını hallettik, artık sıra geldi Sequelize ayarlarına. İlk olarak Sequelize ile bağlantı yapacağımız veritabanı bilgilerini girmemiz gerekiyor. “E az önce models klasörü altındaki index.js dosyasında yeni bir Sequelize nesnesi oluştururken bunu zaten yaptık” diyebilirsiniz fakat orada model yapısı için veritabanı bağlantı bilgilerini girdik, burada Sequelize için gireceğiz. Ana dizinde bir tane config.js adında Javascript dosyası oluşturalım ve index.js dosyasında Sequelize nesnesi oluştururken verdiğimiz objeyi aynen dışarı export edelim. Sequelize bu dosyayı okuyacak ve buna göre veritabanına bağlantı yapacaktır.

module.exports = {
    host: 'localhost',
    port: 3306,
    username: 'root',
    password: '',
    database: 'kutuphane',
    dialect: 'mysql'
};

Sequelize için gerekli olarak ayarlamaları yaptığımıza göre artık .sequelizerc dosyasına geçebiliriz. Sequelize bu dosyayı okuyarak gerekli olan dosya ve klasör yollarını tespit edebiliyor ve veritabanına bağlantı yapabiliyor yada sequelize-cli komutları çalıştırabiliyoruz. Şimdi bu dosyayı yazabilmek için bizim seeders ve ve migrations klasörlerine ve bu klasörlerin yollarına ihtiyacımız olacak. Bu zamana kadar bu klasörleri oluşturmamıştık ama şimdi oluşturalım ve ardından .sequelizerc dosyasını yazalım;

const path = require('path');
module.exports = {
    'config': path.resolve('./config.js'),
    'models-path': path.resolve('./models'),
    'seeders-path': path.resolve('./seeders'),
    'migrations-path': path.resolve('./migrations')
};

Eveett Sequelize ile Javascript tarafında yapacaklarımız bu kadardı. Artık veritabanını oluşturma adımına geçebiliriz. Veritabanı işlemlerini terminal üzerinden yapacağız ve sequelize yada sequelize-cli komutlarını kullanacağız. sequelize ve sequelize-cli komutları doğrudan terminal üzerinden çalıştırılabilir komutlar değil, o yüzden npx komutunun altında çalıştıracağız. Örneğin veritabanını oluşturmak için

npx sequelize db:create

veritabanı ile beraber tabloları da oluşturmak isterseniz

node ./connection.js

Veritabanına çalıştırmak istediğiniz migrationlar için

npx sequelize db:migrate

Veritabanını kaldırıp tekrardan kurmak, migration ve seeder dosyalarını çalıştırmak için ise

npx sequelize db:drop && npx sequelize db:create && node ./connection.js && npx sequelize db:migrate && npx sequelize db:seed:all

komutlarını çalıştırmanız yeterli. Bu komutların ardından istediğiniz işlemi npx ve sequelize (yada sequelize-cli) komutu yapacaktır.

Evet bu yazımızda bu kadardı. Tüm Node.JS derslerimize buraya tıklayarak ulaşabilirsiniz. Herkese hayırlı günler.

Skorumuz:
Oy Vermek İçin Tıklayın
[Toplam: 1 Ortalama: 5]

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Başa dön tuşu