본문 바로가기

FrontEnd

TypeORM 스터디 : QueryBuilder 1편 - CRUD 기본

반응형

TypeORM

 

공식 메뉴얼을 번역 및 정리한 내용이다.

2편 보기

 

TypeORM 스터디 : QueryBuilder 2편 - CRUD 심화

TypeORM - Amazing ORM for TypeScript and JavaScript (ES7, ES6, ES5). Supports MySQL, PostgreSQL, MariaDB, SQLite, MS SQL Server, Oracle, WebSQL databases. Works in NodeJS, Browser, Ionic, Cordova a..

itchallenger.tistory.com

3편 보기

 

TypeORM 스터디 : QueryBuilder 3편 - 캐싱

TypeORM - Amazing ORM for TypeScript and JavaScript (ES7, ES6, ES5). Supports MySQL, PostgreSQL, MariaDB, SQLite, MS SQL Server, Oracle, WebSQL databases. Works in NodeJS, Browser, Ionic, Cordova an..

itchallenger.tistory.com

# 쿼리빌더 사용 시 주의사항

// this works
const result = await getConnection()
    .createQueryBuilder('user')
    .leftJoinAndSelect('user.linkedSheep', 'linkedSheep')
    .leftJoinAndSelect('user.linkedCow', 'linkedCow')
    .where('user.linkedSheep = :sheepId', { sheepId })
    .andWhere('user.linkedCow = :cowId', { cowId });
    
// not works
const result = await getConnection()
    .createQueryBuilder('user')
    .leftJoinAndSelect('user.linkedSheep', 'linkedSheep')
    .leftJoinAndSelect('user.linkedCow', 'linkedCow')
    .where('user.linkedSheep = :id', { id: sheepId })
    .andWhere('user.linkedCow = :id', { id: cowId });

아래의 경우 쿼리빌더가 쿼리를 만들면서 앞의 sheepId를 cowId로 Override할 것이다.

 

 

# 쿼리빌더 사용법

// 커넥션 사용 (이게 깔끔해보임)
import {getConnection} from "typeorm";

const user = await getConnection()
    .createQueryBuilder()
    .select("user")
    .from(User, "user")
    .where("user.id = :id", { id: 1 })
    .getOne();
    
// 엔터티매니저 사용
import {getManager} from "typeorm";

const user = await getManager()
    .createQueryBuilder(User, "user")
    .where("user.id = :id", { id: 1 })
    .getOne();

// 레포지토리 사용
import {getRepository} from "typeorm";

const user = await getRepository(User)
    .createQueryBuilder("user")
    .where("user.id = :id", { id: 1 })
    .getOne();

 

# 쿼리빌더 타입

// Select
import {getConnection} from "typeorm";

const user = await getConnection()
    .createQueryBuilder()
    .select("user")
    .from(User, "user")
    .where("user.id = :id", { id: 1 })
    .getOne();
    
    
// Insert
import {getConnection} from "typeorm";

await getConnection()
    .createQueryBuilder()
    .insert()
    .into(User)
    .values([
        { firstName: "Timber", lastName: "Saw" },
        { firstName: "Phantom", lastName: "Lancer" }
     ])
    .execute();
    
// Update
import {getConnection} from "typeorm";

await getConnection()
    .createQueryBuilder()
    .update(User)
    .set({ firstName: "Timber", lastName: "Saw" })
    .where("id = :id", { id: 1 })
    .execute();
    
    
// Delete
import {getConnection} from "typeorm";

await getConnection()
    .createQueryBuilder()
    .delete()
    .from(User)
    .where("id = :id", { id: 1 })
    .execute();

특이한 타입 : RelationQueryBuilder

메모리 상의 객체를 이용해 join 및 쿼리할 때 사용한다.

import {getConnection} from "typeorm";

await getConnection()
    .createQueryBuilder()
    .relation(Post, "categories") // Post는 엔터티 클래스
    .of(post) // post는 객체
    .add(category); // categorty는 객체
    
// 동일한 효과지만 쿼리가 두번 날라간다.
const postRepository = getRepository(Post);
const post = await postRepository.findOne(1, { relations: ["categories"] }); // categories를 필드로 가져오기 위해 사용한다.
post.categories.push(category);
await postRepository.save(post);

아래의 categories에 1000개의 객체가 있다고 하면, 얼마나 비효율적인 연산이 될 것인가?

위의 쿼리는 쿼리 하나로 DB에서 처리하기 때문에 메모리에 1000개의 객체를 올릴 필요가 없다.

또한 push, save와 같이 조건 입력으로 객체를 꼭 사용할 필요도 없다.

// id가 1인 Post에
// category id가 3인 카테고리 추가
import {getConnection} from "typeorm";

await getConnection()
    .createQueryBuilder()
    .relation(Post, "categories")
    .of(1)
    .add(3);
    
// 복합키를 사용하면...
import {getConnection} from "typeorm";

await getConnection()
    .createQueryBuilder()
    .relation(Post, "categories")
    .of({ firstPostId: 1, secondPostId: 3 })
    .add({ firstCategoryId: 2, secondCategoryId: 4 
    
    
    
import {getConnection} from "typeorm";

// 삭제하기!
await getConnection()
    .createQueryBuilder()
    .relation(Post, "categories")
    .of(post) // you can use just post id as well
    .remove(category); // you can use just category id as well

add와 remove는 many-to-many나 one-to-many에서 사용하는 방법이라 한다.

one-to-one이나 many-to-one은 아래와 같이 set을 사용해야 한다.

(post는 하나, categority는 여러개)

import {getConnection} from "typeorm";

// post와 카테고리는 1대1
// 혹은 n대 1이다.
// 1개는 set으로 설정한다.

await getConnection()
    .createQueryBuilder()
    .relation(Post, "categories")
    .of(post) // you can use just post id as well
    .set(category); // you can use just category id as well
    
// null로 셋하기
import {getConnection} from "typeorm";

// this code unsets category of a given post
await getConnection()
    .createQueryBuilder()
    .relation(Post, "categories")
    .of(post) // you can use just post id as well
    .set(null);

RelationQueryBuilder는 업데이트 말고 select도 가능함

import {getConnection} from "typeorm";

const post = await getConnection().manager.findOne(Post, 1);
// 하나 가져오기
post.categories = await getConnection()
    .createQueryBuilder()
    .relation(Post, "categories")
    .of(post) // you can use just post id as well
    .loadMany();

// 여러개 가져오기
post.author = await getConnection()
    .createQueryBuilder()
    .relation(Post, "user")
    .of(post) // you can use just post id as well
    .loadOne();

 

글이 길어져서 2편에서 계속

 

참고 : 

TypeORM - Amazing ORM for TypeScript and JavaScript (ES7, ES6, ES5). Supports MySQL, PostgreSQL, MariaDB, SQLite, MS SQL Server, Oracle, WebSQL databases. Works in NodeJS, Browser, Ionic, Cordova and Electron platforms.

 

TypeORM - Amazing ORM for TypeScript and JavaScript (ES7, ES6, ES5). Supports MySQL, PostgreSQL, MariaDB, SQLite, MS SQL Server,

 

typeorm.io

 

반응형