TypeScript ve JavaScript Icin Bir ORM: TypeORM

Merhaba. Bu yazıda TypeScript ve JavaScript Icin Bir ORM: TypeORM hakkında açıklamalarda bulunacağım. Bir onceki yazida SQL Server hakkinda bilgiler mevcut.

TypeScript ve JavaScript Icin Bir ORM: TypeORM

TypeScript ve JavaScript Icin Bir ORM: TypeORM

Oncelikle TypeORM gercekten bir ORM. TypeScript ile yazilmis. NodeJS, Browser, Cordova, PhoneGap, Ionic, React Native gibi birden fazla teknolojide kullanilabiliyor. Tabi JavaScript tarafinda ES5 destegi de sunuyor.

TypeORM hem Active Records yapisini hem de Data Mapper yapisini ayni anda size sunmakta. Hangisini tercih ederseniz onu kullanabilirsiniz. Bunun avantaji daha maintainable uygulamalar yazmaniza imkan tanimasi tabi.

Kendisi bircok ORM'in destekledigi ozellikleri sunuyor. Zaten Java dunyasindan bildigimiz Hibernate, PHP dunyasindan bildigimiz Doctrine ve .NET tarafinin krali olan Entity Frameworkten esinlenerek olusturulmus. Coklu kalitim desenini destekliyor. Ayrica tek yonlu ya da cok yonlu calisilabildigi gibi kendi kendinin referansi olabilir.

Acikcasi tum bilgileri yazmak isterdim ancak cok uzun bir yaziya donusecek.

Kurulum

Kurulum npm uzerinden gerceklesiyor. Muhtemelen yarn uzerinde de mevcuttur. Ama biz npm uzerinden kurulum gerceklestirecegiz.

npm install typeorm --save

npm install typeorm -g // global kurulum

Bunun ardindan reflect metadata modulune de ihtiyacimiz var onu da kuralim

npm install reflect-metadata --save

Ihtiyac duyma ihtimalimize karsin asagidaki modulu de kuralim:

npm install @types/node --save

Sorun yasamadiysak TypeORM kurulumunu basariyla gerceklestirdik. Yukarida iki kurulum turu var. Birincil tur proje bazli. Digeri ise global olani. Biz global uzerinden ilerleyecegiz ilk basta.

Ben bu yazida PostgreSQL kullandim. Bundan dolayi da baglantilarimi saglayabilecegim bir wrapper kurmam gerekiyor.

npm install pg --save

Ilk Uygulamamiz

Simdi TypeORM ile ilk uygulamamizi yapalim. Komut satirina su komutu verelim:

typeorm init --name Library --database postgres

Bu komut Library adinda bir proje olusturacak. Veri tabani olarak da postgresql kullanacak. Tum database turleri icin asagidakiler kullanilabilir:

mysql, mariadb, postgres, sqlite, mssql, 
oracle, mongodb, cordova, react-native

Ardindan cd komutu ile Library klasorune gidelim. Ve bagimliliklari kuralim:

cd Library
npm install

Bu yontem yukarida yaptigimiz tabiri caizse amelelikten kurtulmamiza imkan taniyacak. Cunku yukaridaki adim adim npm install yerine typeorm-cli bunu sizin icin hallediyor. Simdi proje klasorunuzde ormconfig.json adinda bir dosya bulunmakta. Bu dosyada database ayarlarini configure etmeniz gerekmekte. Ornegin benim ayarlar bu sekilde:

TypeScript ve JavaScript Icin Bir ORM: TypeORM

 

Ardindan hemen asagidaki komutu calistiralim:

npm start

Fark ettiyseniz sanki ufak bi hareketlenme oldu bir seyler eklemeye calisti gibi. Bu arada olusturdugumuz entityler ve migrationlarin nerede bulundugunu da goruyoruz yukaridaki gorselde. Bu dosya dedigim gibi ormconfig.json dosyasi. Tabi burada migration islemlerine falan girisecek isek bunu package.json dosyasinda duzenlememiz cok daha iyi olacak. Ornegin bir migration yapacagiz:

typeorm migration:create -n UserMigration

Ardindan bu migrationlarin run edilmesi gerekiyor. Bu asamada package.json dosyamiz soyle olacak:

{
   "name": "Library",
   "version": "0.0.1",
   "description": "Awesome project developed with TypeORM.",
   "devDependencies": {
      "ts-node": "3.3.0",
      "@types/node": "^8.0.29",
      "typescript": "2.5.2"
   },
   "dependencies": {
      "typeorm": "0.2.0",
      "reflect-metadata": "^0.1.10",
      "pg": "^7.3.0"
   },
   "scripts": {
      "start": "ts-node src/index.ts",
      "migrate": "ts-node ./node_modules/.bin/typeorm migration:run"
   }
}

Bu sayede npm run migrate dedigimizde migrationlar gerceklesecek. Neyse fazla uzatmayalim.

Ilk Modelimizi Yazalim

Yeni bir entity olusturacagiz. Bunun icin entity klasoru altina sececeginiz isimde bir dosya olusturun. Mesela Post.ts gibi. Ornegin benim model dosyam asagidaki gibi:

import {Entity, PrimaryGeneratedColumn, Column} from "typeorm";

@Entity()
export class Post {
    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    AuthorID: number;

    @Column()
    CategoryID: number;

    @Column()
    title: string;

    @Column()
    content: string;
}

Class icerisinde kullanilan decoratorler o kolonun ne oldugunu belirtiyorlar. Ornegin id icin PrimaryGeneratedColumn decoratorunu ayarlamisiz ki bunun postgresql database yapisinda serial turunden bir kolon oldugunu belirtelim diye. Decoratorler veri turu cinsinden parametre de aliyorlar. Ornegin:

import {Entity, PrimaryGeneratedColumn, Column} from "typeorm";

@Entity()
export class Post {
    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    AuthorID: number;

    @Column('int')
    CategoryID: number;

    @Column()
    title: string;

    @Column()
    content: string;
}

Database'e Ilk Verilerimizi Ekleyelim

Simdi proje dizinimize gidelim. Burada yer alan index.ts dosyasinda zaten hazirda bir yapi var ama biz kendi yazdigimiz modelden veri tabani tablosu uretip bu tabloya ekleme gerceklestirecegiz:

createConnection() isimli fonksiyonun icerisinde asagidaki kodu yazalim ve aciklayalim:

let post = new Post();

post.AuthorID = 1;
post.CategoryID = 2;
post.title = "Test Article 2";
post.content = "The content for test article 2";
await connection.manager.save(post);
console.log("Saved a new post with id: " + post.id);
    
console.log("Loading posts from the database...");
const posts = await connection.manager.find(Post);
console.log("Loaded posts: ", posts);

Oncelikle entity framework tarafindan asina olanlar icin bu yapi tanidik geliyor. Burada tek farkli olan attributelara yani kolonlara degerlerini verdikten sonra connection manager'da bulunan save metoduna instance passlaniyor. Bu connection manager promise donuyor. Bu yuzden await keywordunu yazdik. Ardindan da eklenen icerige dair belirttigimiz primary kolonun degerini alabiliyoruz.

findOne() ile ID'ye Gore Getirme

Eger auto complete ozelligine sahip bir  editore sahipseniz manager'dan sonra otomatik tamamlanan metodlarda delete, update gibi metodlarin hatta ID'lere gore getirme ozelliginin de oldugunu gorebilirsiniz. Ornek:

import "reflect-metadata";
import {createConnection} from "typeorm";
import {Post} from "./entity/Post";

createConnection().then(async connection => {

    

    const getPostById = await connection.manager.findOne(Post, 2);

    console.log(getPostById);
    
}).catch(error => console.log(error));

findByIds() ile Birden Fazla ID'ye Gore Sorgulama

Yukaridaki yontem tek bir sonuc dondurecektir. Eger belirttiginiz birden fazla ID'ye gore deger getirmek isterseniz asagidaki yapi size uygun olacaktir:

import "reflect-metadata";
import {createConnection} from "typeorm";
import {Post} from "./entity/Post";

createConnection().then(async connection => {

    

    const getPostById = await connection.manager.findByIds(Post, [2]);

    console.log(getPostById);
    
}).catch(error => console.log(error));

find() Fonksiyonu ile Tum Kolonlarda Sorgulama

Eger bunlarin disinda var olan kolonlara gore bir sorgulama yapmak istiyorsaniz asagidaki yapiyi kullanmaniz daha iyi olacaktir:

import "reflect-metadata";
import {createConnection} from "typeorm";
import {Post} from "./entity/Post";

createConnection().then(async connection => {

    

    const getPostById = await connection.manager.find(Post, {
        title: 'Test Article 2',
    });

    console.log(getPostById);
    
}).catch(error => console.log(error));

Query Builder

İsterseniz query builder ile guvenli bir sekilde queryler olusturabilirsiniz. Ornek bir sorgu:

import "reflect-metadata";
import {createConnection} from "typeorm";
import {Post} from "./entity/Post";

createConnection().then(async connection => {

    

    const getPostWithQuerybBuilder = await connection.getRepository(Post)
                                        .createQueryBuilder("post")
                                        .where("post.id = :id and post.CategoryID = :CatID", { id: 2, CatID: 2})
                                        .getMany();

    console.log(getPostWithQuerybBuilder);
    
}).catch(error => console.log(error));

Bu yazida TypeScript ve JavaScript Icin Bir ORM: TypeORM hakkinda ufak tefek bilgiler elde ettik.

Umarim faydali olabilmisimdir. Sadece soylemek istediklerim siz bunu direkt bi CLI tool icin kullanacaksaniz queryler yavas calisiyor. Yani result alindiktan sonra close islemi uzun suruyor. Belki benim makinemle alakalidir. Eksik ya da hatali noktalarin oldugunu dusunuyorsaniz bu yazi altina yorum atarak o kisimlari duzeltmemi saglayabilirsiniz.

Resmi Site: http://typeorm.io

OKudugunuz icin tesekkur ederim. Iyi calismalar.