Blog

Sequelize ile Tablo İlişkileri Nasıl Yapılır?

Sequelize Nedir?

Sequelize, NodeJs tabanlı bir ORM (Object-Relational Mapping) yazılımıdır. Veritabanı yapılarını Obje ve onun fonksiyonlarına çevirerek, kod içerisinde direkt SQL query’leri yazmadan, kod tarafında işin halledilme olayıdır kısaca. Yani veritabanı bizim bir objemiz olur ve orm’deki methodlar vasıtasıyla CRUD işlemleri gerçekleştirebiliriz.

Sequelize’da 4 adet ilişki türü vardır, bunlar hasOne,hasMany,belongsTo ve belongsToMany’dir. SQL tablolarımızdaki ilişkilerimizden yola çıkarak relationship yapısını bu dört yöntem/method ile halledebiliriz. Bunların kullanım mantığı, tablomuzdaki target(hedef) ve source(kaynak) tablo yapısına göre ayarlanır. Şimdi yazımızın en önemli kısımlarından biri olan target ve source tablomuz hakkında konuşalım.

Target ve Source'u Belirleme

target-source

Yukarıdaki örnek instructor ve subject tablomuza baktığımızda, bir one to one relationship örneği görüyoruz. Bu tabloda bizim target yani hedef tablomuz, Instructor tablosu ve source yani kaynak tablomuz Subject tablosu. Subject(source) tablosundan Instructor(target) tablosuna bir one-to-one ilişkimiz var.

Aşağıdaki tablomuzda ise gördüğümüz üzere bir one to many ilişkimiz var ve görüldüğü üzere Instructor’dan Class’a gidiyoruz, yani burada ise Instructor tablomuzun bizim source tablomuz olduğunu ve Class tablomuzun target tablomuz olduğunu görüyoruz.

target table

Aynı şekilde many to many tablomuz da benzer bir ilişki içerisinde. Burada ise Student ve Class tablolarımız bizim source tablolarımız ve aradaki orta tablomuz ise bizim target tablomuz.

Sequelize Table

Source ve Target tablomuzu nasıl belirlediğimizi bulduktan sonra sırada bu dört ilişkiyi nasıl kullanabileceğimiz kuralına geliyoruz. Bu kural iki adet maddeden oluşuyor ve sequelize’da relationship’leri ayarlamamız için bu iki kural’dan yola çıkacağız.

Kurallar

  • Her zaman source tablosundan target tablomuza doğru yola çıkacağız. Bu bağlamda doğru bir ilişkimiz olması için, source tablomuzu iyi belirlemeliyiz.

[ Source model ] . [ İlişki Türü ] ([ Target model ],options objesi)

  • Bu kuralımızda, foreign key yani yabancı anahtarımızın hangi tabloda olacağına bakacağız.
    1. Eğer bizim yabancı anahtarımız source model’imizin içerisinde ise, belongsTo veya belongsToMany kullanacağız.
    2. Eğer bizim yabancı anahtarımızın target model’imizin içerisinde ise, hasMany ve hasOne anahtar kelimesini kullanacağız.

Yani bu kurallardan yola çıkarak şöyle özetleyebiliriz; Eğer bizim yabancı anahtarımız, ana tabloda ise, belongsTo veya belontsToMany kullanıyoruz, eğer karşı tabloda ise hasOne ve hasMany kullanıyoruz.

Tablomuz Ve İlişkilerimiz

Sequelize Table Example

Yukarıdaki veritabanı tasarımımızda source ve target tablolarını belirleyerek işe başlıyoruz.

  • Subject’den Instructor’a One to One ilişki, Subject burada bizim source tablomuz, Instructor burada bizim target tablomuz. Foreign Key’in Instructor tablosu yani target içinde olduğunu görüyoruz, yani burada ilişkimiz Subject.hasOne(Instructor) şeklinde olacak. Tam tersi bir şekilde bağlamak için ise Instructor.belongsTo(Subject) olacak.
  • Instructor’dan Class’a bir One to Many ilişkimiz var. Instructor burada bizim source tablomuz, Class ise target tablomuz. Yani burada ilişkimiz Instructor.hasMany(Class) şeklinde olacak. Ve yine, Class’tan da Instructor tablosuna erişebilmek istersek eğer Class.belongsTo(Instructor) bağlantısı verebiliriz. Neden belonsTo kullanabildik? Çünkü bu şekilde Source tablomuz’u değiştirdik ve Foreign key source tablosuna taşındığı için belongsTo kullandık.
  • Student Class ilişkimiz ise Many to Many bir ilişki fakat burada bir ara tablo olduğu için, burada diğer kuralları biraz ihlal etmiş olacağız, bu bizden değil sequelize’ın kendi yapısından kaynaklanan bir kural.. Student ve Class tablolarımız burada bizim source yani kaynak tablolarımız olmasına rağmen, burada bir ara tablo olduğu için, belongsToMany kullanmak zorundayız. Student.belongsToMany(Class) yapısını kullanacağız.

Kurulum

Eğer bir sequelize projesini nasıl kuracağınızı merak ediyorsanız, MDP’de yazılım geliştirici olan Burak Yılmazer’in Sequelize Nedir yazısına ulaşarak, kurulumu yapabilirsiniz. Bizim burada asıl amacımız sequelize’da ilişkileri kullanarak bir örnek yapmak. Bu yüzden kurulum adımlarını atlıyorum.

Komut satırından ‘sequelize init’ yaparak projemizi başlatıyoruz ve bize bir proje yapısı getiriyor. Bu proje yapımız, config,migrations,models şeklinde geliyor. app.js’i projeyi test etmek ve route’ları ayarlamak için kendim oluşturdum.

Sequelize Root

İlk olarak işe config.json’ı ayarlayarak başlıyoruz. Bu dosyayı doğru ayarlamamız veritabanına bağlanabilmemiz için önemli. Ben aşağıda gördüğünüz gibi lokal ortamımdaki postgres’e bu şekilde bağlandım. Developmen modda çalışacağımız için sadece development modu değiştirsek şimdilik yeterli olur.

Postgres

Komut satırından sequelize db:create diyerek database’imizi postgres içerisinde sequelize orm paketimiz aracılığıyla oluşturuyoruz.

Model oluşturmak

Model’lerimizi oluşturarak işe başlıyoruz. Bu model’ler bizim SQL’de entity diye tabir ettiğimiz verilerdir.

Şu kodları sırasıyla yazarak Modellerimizi oluşturabiliriz.

Student’imiz name,surname ve email alacak ve class harici bir yere bağlı olmayacak, o modeli şu şekilde oluşturuyoruz:

sequelize model generate --name Student --attributes name:string,surname:string,email:string 

Class’ımız hem Instructor’a hem de Student’a bağlı olacak. İçinde foreign key olarak instructorId tutacak yani class’a bir sorgu attığımızda instructorId’de beraberinde gelecek.O modeli bu şekilde oluşturuyoruz.

sequelize model:generate --name Class --attributes instructorId:integer,classCode:string  

StudentClass  tablomuz many-to-many ilişki içinde olduğundan dolayı, bir ara tablo sayılacak ve classId ve studentId’yi tutacak.Onu bu şekilde oluşturabiliriz:

sequelize model:generate --name StudentClass --attributes classId:integer,studentId:integer

Instructor ile Subject arasında bir One to One ilişki olduğu için, Instuctor’ın içinde bir foreign key olan SubjectId’yi tutuyoruz. Böylece Instrutor’a sorgu attığımızda bize subjectId’yi de getirecek, böylece sequelize’dan tek sorgu’da her iki özelliğe de ulaşabileceğiz. Kodu şu şekilde oluşturabiliriz.

sequelize model:generate --name Instructor --attributes instructorDegree:string,name:string,surname:string,subjectId:integer   

Son olarak Subject öğretmenlerde belirtileceği için, sadece name içerek, kodunu bu şekilde oluşturabiliriz:

sequelize model:generate --name Subject --attributes subjectName:string

Daha sonra komut satırından db:migrate komutunu çalıştırdığımızda, bu modeller üzerinde migration oluşturup, modeli kalıcı olarak database’e kaydeder. Şuraya dikkat etmekte fayda var, model isimlerini her ne kadar tekil olarak kod üzerinde generate(oluşturmak) etsek de, bunlar  SQL’de çoğul ve büyük harf olarak geçebilir, bunun da çözümü, eğer tabloda bir bütünlük sağlamak istiyorsak, daha sonradan bu class’a tableName parametresi vererek bu bütünlüğü sağlabiliriz.

Örnek bir student tablosunun model ve tablo name’i şu şekilde olabilir:

Sequelize Tablo Örneği

One To One İlişki

One-to-One ilişki, bir kaynak modelin (source model) bir hedef modeli (target model) ile sadece bir kez ilişkili olabileceğini belirtir. Yukarıda target ve source’dan bahsettiğimiz için şimdi işimiz daha kolay olacak. Source modelimiz Subject ve target modelimiz Instructor, foreign key’imiz ise target tablomuzda, bu yüzden hasOne kullanıyoruz.

subject.js

Subject.js

Bağlantımızı gerçekleştirebilmemiz için yabancı anahtarı oluşturduğunuz modelin migration dosyasında, diğer modeline (referred model) references vermeniz gerekmektedir. Örneğin, Instructor modelinde bir Subject'e ait olma ilişkisi oluşturduysanız, Instructor modelinin migration dosyasında Subject modeline reference vermeniz gerekir. Bu, Instructor tablosunun Subject tablosundaki bir satıra referans etmesini sağlar ve Instructor'ın Subject ile ilişkili olduğunu gösterir.

20230201071547-create-instructor.js:

Instructor Subject

Many To One İlişki

Many-to-One ilişki, bir kaynak modelin(source), bir hedef modeli ile(target), birden fazla ilişkili olabileceği anlamına gelir. Burada bizim source modelimiz Instructor ve target modelimiz Class. Foreign key’imizin target modelde olduğunu görüyoruz. Bu yüzden kullanacağımız ilişki türü hasMany. Tam tersi taraftan bağlamak istediğimizde ise source tablomuz değişeceği için ve foreign key’imiz de source tablomuzda olduğu için, belongTo ilişkisini kullanacağız.

instructor.js

instructor.js

class.js

Class.js

Bağlantımızı gerçekleştirebilmemiz için yabancı anahtarı oluşturduğunuz modelin migration dosyasında, diğer modeline (referred model) references vermeniz gerekmektedir. Örneğin, Class modelinde bir Instructor'a ait olma ilişkisi oluşturduysanız, Class modelinin migration dosyasında Instructor modeline references vermeniz gerekir. Bu, Class tablosunun Instructor tablosundaki bir satıra referans etmesini sağlar ve Class'ın Instructor ile ilişkili olduğunu gösterir.

20230201071158-create-class.js

Create Class

Many to Many ilişki

Many-to-Many ilişkimizde bir istisna vardı. Bu ilişkide source modelimizden target ara tablomıza gitmemize ve foreign key’lerin ana tabloda olmasına rağmen , sequelize’ın kuralları gereği belongsToMany vermeliydik. Her iki tablodaki verilere de birbiri aracılığı ile ulaşmak için hem Class hem Student tablomuzda bunu yapabiliriz. 

student.js

Student.js

class.js

Sequelize Tablo

Son olarak studentclass migration dosyamızın içine referans vererek, bu satırları tablomuzun içinde oluşturup bağlantımızı tamamlıyoruz.

20230201071320-create-student-class.js

Create Student Class
Sequelize ile tablo oluşturma

Github repom’daki kodların tamamına bu linkten ulaşabilirsiniz.

Tablonun çizimine ise Lucidchart üzerinden ulaşabilirsiniz.


Benzer
Bloglar

Mailiniz başarıyla gönderilmiştir en kısa sürede sizinle iletişime geçilecektir.

Mesajınız ulaştırılamadı! Lütfen daha sonra tekrar deneyin.