[TypeORM] TypeORM의 패턴들을 알아보자

lnnae·2020년 7월 14일
2

Active Record 패턴

Entity에 쿼리 메소드를 정의하고, 쿼리 메소드를 사용하여 객체를 저장, 제거, 불러온다.

BaseEntity를 사용하여 새로운 클래스에 상속하게 한 후 사용할 수 있다.

BaseEntity

모든 Active Record entity들은 BaseEntity를 상속해야한다. 그리고 이것은 여러 메소드들을 제공한다. (save, remove, find, findOne... )

BaseEntity가 갖고 있는 메소드와 Entity 내에서 사용자가 정의한 static 메소드를 이용할 수 있다.

BaseEntity는 대부분의 standard Repository가 가진 method들을 수행할 수 있다.
active record entity를 사용하는 경우 Repository나 Entity Manager를 사용할 필요가 없다.

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

@Entity()
export class User extends BaseEntity {

    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    firstName: string;

    @Column()
    lastName: string;

    @Column()
    isActive: boolean;

    static findByName(firstName: string, lastName: string) {
        return this.createQueryBuilder("user")
            .where("user.firstName = :firstName", { firstName })
            .andWhere("user.lastName = :lastName", { lastName })
            .getMany();
    }
}

//사용은
const timber = await User.findByName("Timber","Saw");

Data Mapper 패턴

typeORM에서는 Active Record와 Data Mapper 패턴을 둘 다 사용할 수 있다.

Repository를 이용하여 객체를 저장, 제거, 불러온다.

Active Record 패턴과 차이점은 모델에 접근하는 방식이 아닌 Repository에서 데이터에 접근한다는 것이다.

import { EntityRepository, Repository } from 'typeorm';
import { User } from '../entity/User';

@EntityRepository()
export class UserRepository extends Repository<User> {

	findByName(firstName: string, lastName: string) {
      		return this.createQueryBuilder("user")
              .where("user.firstName = :firstName", {firstName})
              .andWhere("user.lastName = :lastName", {lastName})
              .getMany();
	}
}

const userRepository = connection.getCustomRepository(UserRepository);
const timber = await userRepository.findByName("Timber", "Saw");

그래서 최종 선택은?

Data Mapper는 큰 서비스에서 유지 보수하기 좋다.
Active Record는 비교적 간단해서 작은 서비스에서 유지보수하면서 사용하기에 좋다.
필요에 따라 적절히 섞어쓰는 방식이 좋을 듯 합니다,, 🤔

QueryBuilder

TypeORM의 가장 강력한 기능 중 하나라고 한다. 이걸 사용하면 SQL query를 하여튼 멋지고 편리하게 쓸 수 있다는 듯.. 그리고 자동으로 Entity로 변환해 반환한다!

How to use..

import { getRepository } from 'typeorm';

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

Repository를 이용해 queryBuilder를 작성하는 방식이다.

여기서 createQueryBuilder("user")에서 user는 SQL alias이다. mysql을 예로 들자면 SELECT users AS user 이런 느낌이라고 할 수 있겠다. 이것은 어디서든 사용할 수 있다. 여기서 사용하는 user는 테이블 명을 의미하고, '.' 아래로 써 내려가는 sql query에서 사용할 수 있다.

하나의 query builder는 한 개의 alias만 가질 수 있는게 아니라 여러 개의 alias를 가질 수 있다. 여러 테이블마다 alias를 가지게 할 수 있고, 여러 테이블을 join할 수 도 있다.

결과 가져오기

QueryBuilder에서 entity와 raw 두가지로 결과를 가져올 수 있다.

DB에서 단일한 결과를 가져오려면 .getOne()을 사용하고, 여러 개의 결과를 가지고오려면 .getMany()를 사용하면 된다.

특정 데이터를 가져와야할 때(ex. sum) 는 entity가 아니라 raw data이다. 이런 결과값을 가져올 때 .getRawOne().getRawMany()를 사용해서 결과값을 가져온다.


Reference

profile
이내임니당 :>

0개의 댓글