영호

[TypeORM] TypeORM entity 작성 본문

TypeORM

[TypeORM] TypeORM entity 작성

0h0 2022. 5. 14. 15:47
반응형

들어가며

TypeORM을 사용하며 entity 작성하는 방법을 알아볼 예정입니다.

포스팅에서 바탕이 되는 ERD는 팀 프로젝트를 진행하며 설계한 ERD의 일부를 사용할 예정입니다.

USER(1) <-> PARENT(1) -> 일대일 관계
USER(1) <-> BABYSITTER(1) -> 일대일 관계

TypeORM entity관련 기본적인 데코레이션

@PrimaryGeneratedColumn

  • 이름 그대로 PK를 생성해주는 데코레이션입니다.
  • autoIncrement가 적용된 데코레이션입니다.

@PrimaryColumn

  • PK를 생성해주지만 autoIncrement는 지원하지 않는 데코레이션입니다.

@Column

  • 이름 그대로 column을 생성할 때 기본으로 사용되는 데코레이션입니다.

다양한 column option, type

@Column("int")
or 
@Column({ type: "int" })

// 길이를 200으로 제한한다.
@Column("varchar", { length: 200 })

// not null 옵션과 데이터 타입을 number로 설정한다.
@Column({nullable : false})
    code: number;
  • TypeORM은 DB에서 지원하는 데이터 타입은 다 지원을 하고 이에 더해 json, list 등 다양한 타입을 지원합니다. 자세한 내용은 공식문서를 보면 매우 많이 정보를 확인할 수 있습니다.

연관관계 설정하기

OneToOne관계

  • babysitter와 user는 일대일 관계이고 foreign key는 babysitter에 생성되는 코드입니다.
// Babysitter.ts
@OneToOne(() => User, {onDelete: 'CASCADE' })
@JoinColumn()
user_id: User
- @OneToOne을 통해 일대일 관계라는 것을 명시해주면서, 어느 엔티티와 관계가 있는지 명시해줍니다.
- onDelete는 넣어도 되고 안 넣어도 되는 옵션이다.@JoinColumn을 통해 foreign key를 생성합니다.
- 나는 양방향 연관관계는 필요 없어서 작성을 안 했지만 필요하다면 User.ts에도 @OneToOne을 명시해주면 됩니다.

 

OneToMany, ManyToOne 관계

  • 해당 관계에서는 @JoinColumn은 생략 가능합니다.
  • @OneToMany는 @ManyToOne이 필요하지만 역은 해당되지 않습니다.
    • OneToMany를 사용하려면 연관된 entity에 반드시 ManyToOne을 설정해야 하지만, ManyToOne은 연관된 entity에 OneToMany를 반드시 설정하지 않아도 된다는 뜻입니다.
  • 공식문서 코드를 가져다 쓰겠습니다.
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne } from "typeorm"
import { User } from "./User"

@Entity()
export class Photo {
    @PrimaryGeneratedColumn()
    id: number

    @Column()
    url: string

    @ManyToOne(() => User, (user) => user.photos)
    user: User
}
import { Entity, PrimaryGeneratedColumn, Column, OneToMany } from "typeorm"
import { Photo } from "./Photo"

@Entity()
export class User {
    @PrimaryGeneratedColumn()
    id: number

    @Column()
    name: string

    @OneToMany(() => Photo, (photo) => photo.user)
    photos: Photo[]
}

ManyToMany 관계

  • @JoinTable을 이용해 구현할 수 있습니다.
  • @JoinTable은 관계의 한쪽(소유) 쪽에 넣어야 합니다.
  • eager 옵션은 N+1 문제를 제어할 수 있습니다.
import { Entity, PrimaryGeneratedColumn, Column } from "typeorm";

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

    @Column()
    name: string;
}
import { Entity, PrimaryGeneratedColumn, Column, ManyToMany, JoinTable } from "typeorm";
import { Category } from "./Category";

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

    @Column()
    title: string;

    @Column()
    text: string;

    @ManyToMany(() => Category)
    @JoinTable()
    categories: Category[];
}
+-------------+--------------+----------------------------+
|                        category                         |
+-------------+--------------+----------------------------+
| id          | int(11)      | PRIMARY KEY AUTO_INCREMENT |
| name        | varchar(255) |                            |
+-------------+--------------+----------------------------+

+-------------+--------------+----------------------------+
|                        question                         |
+-------------+--------------+----------------------------+
| id          | int(11)      | PRIMARY KEY AUTO_INCREMENT |
| title       | varchar(255) |                            |
| text        | varchar(255) |                            |
+-------------+--------------+----------------------------+

+-------------+--------------+----------------------------+
|              question_categories_category               |
+-------------+--------------+----------------------------+
| questionId  | int(11)      | PRIMARY KEY FOREIGN KEY    |
| categoryId  | int(11)      | PRIMARY KEY FOREIGN KEY    |
+-------------+--------------+----------------------------+
그러나 Many-To-Many관계를 이렇게 사용하기보다는 위에서 알아본 One-To-Many, Many-To-One을 이용해 풀어서 사용하는 것이 더 좋습니다.

User, Babysitter entity 전체 코드

// entity/User.ts
import {Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, Timestamp} from "typeorm";

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

    @Column({nullable : false})
    email: string;

    @Column({nullable : false})
    username: string;

    @Column({nullable : false})
    nickname: string;

    @Column({nullable : false})
    password: string;

    @Column({nullable : false})
    code: number;

    @CreateDateColumn({
        
    })
    createdAt: Timestamp

}
// BabySitter.ts
import {Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, Timestamp, ManyToOne, OneToMany, OneToOne, JoinColumn} from "typeorm";
import {User} from './User';
import {Mapping} from './Mapping'

@Entity()
export class BabySitter {

    @PrimaryGeneratedColumn()
    id: number;

    @Column({nullable : false})
    age: number;

    @Column({nullable : false})
    gender: string;

    @Column({nullable : false})
    region: string;

    @Column({nullable : false})
    career: string;


    @CreateDateColumn({})
    createdAt: Timestamp


    @OneToOne(() => User, {onDelete: 'CASCADE' })
    @JoinColumn()
    user_id: User

    // babysitter(1) <->  user(N)
    @OneToMany(
        type => Mapping,
        mapping => mapping.babySitter,{ nullable: false, onDelete: 'CASCADE' }
    )
    mapping: Mapping

}

@CreateDateColumn

  • 데이터가 생성된 시간 정보를 자동으로 생성해주는 데코레이션이다. 유용하게 사용할 데코레이션입니다.
  • 이 외에도 @UpdateDateColumn, @DeleteDateColumn 등이 있습니다.
  • 위와 같은 다양한 데코레이션 설명 역시 공식문서를 참고하면 됩니다.

마무리

  • ORM은 이번 프로젝트를 하면서 처음 사용해보는데 아직 익숙하지 않아서 그런지 조금 불편하지만 나름 재밌었습니다.
반응형

'TypeORM' 카테고리의 다른 글

[TypeORM] @Transaction 적용  (0) 2022.05.20
[TypeORM] Active-record 패턴  (0) 2022.05.19
[TypeORM] 공식문서로 TypeORM + MySQL설정하기  (0) 2022.05.09
Comments