영호
[TypeORM] TypeORM entity 작성 본문
들어가며
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