본문 바로가기
DB/typeORM

시작하기 - Entity 관계 만들기(MySQL Key종류)

by 싯벨트 2022. 10. 19.
728x90

# 일대일 관계 만들기(one-to-one)

- @OneToOne 데코레이터를 사용하고, 안에 연결하고 싶은 엔티티를 다음과 같은 형식으로 기재한다. () => <Entity>

- @JoinColumn 데코레이터를 사용해서 관계 설정 시 중심이 되는 엔티티를 표현한다. (Owner side of the relationship)

// photometadata.entity.ts

import {
  Column,
  Entity,
  JoinColumn,
  OneToOne,
  PrimaryGeneratedColumn,
} from 'typeorm';
import { Photo } from './photo.entity';

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

  @Column('int')
  height: number;

  @Column('int')
  width: number;

  @Column()
  orientation: string;

  @Column()
  compressed: boolean;

  @Column()
  comment: string;

  @OneToOne(() => Photo)
  @JoinColumn()
  photo: Photo;
}

# 관계 반전

  • 관계는 단방향, 양방향 가능
  • 단방향의 관계에서는 관계의 소유권이 있는 엔티티가 아니라면 데이터에 접근하기가 복잡하다. 이를 해결하기 위해 관계를 양방향으로 만들어 준다
    • @OneToOne(() => Photo, (photo) => photo.metadata) 일대일 관계를 양쪽으로 설정
    • Photo 엔티티(소유권이 없는 엔티티)에도 @OneToOne 데코레이터 사용하여 양쪽으로 관계 설정 및 metadata 컬럼 명시
    • @OneToOne(() => PhotoMetadata, (photoMetadata) => photoMetadata.photo) metadata: PhotoMetadata
//photo.entity.ts

import {
  Column,
  Entity,
  ManyToMany,
  ManyToOne,
  OneToOne,
  PrimaryGeneratedColumn,
} from 'typeorm';
import { PhotoMetadata } from './photometadata.entity';
import { Author } from './author.entity';
import { Album } from './album.entity';

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

  @Column({ length: 100 })
  name: string;

  @Column('text')
  description: string;

  @Column()
  filename: string;

  @Column('double')
  views: number;

  @Column()
  isPublished: boolean;

  @OneToOne(() => PhotoMetadata, (photoMetadata) => photoMetadata.photo, {
    cascade: true,
  })
  metadata: PhotoMetadata;

  @ManyToOne(() => Author, (author) => author.photos)
  author: Author;

  @ManyToMany(() => Album, (album) => album.photos)
  albums: Album[];
}

# 오류 발생

  • 관계를 설정하며 엔티티의 속성이 없는 상황에서 공식문서에 기재된 관계식을 적으면 에러가 발생한다. 관계를 맺는 엔티티의 양쪽 코드를 모두 완성하면 오류가 사라진다.
  • 해당 모듈(photo) app모듈에 새로 추가한 엔티티를 반영해준다.

# 다대일, 일대다 관계 만들기 (many-to-one / one-to-many)

작가는 사진을 여러 개 소유할 수 있고, 사진은 작가를 하나만 소유할(할당받을) 수 있다. 

//author.entity.ts

import { Column, Entity, OneToMany, PrimaryGeneratedColumn } from 'typeorm';
import { Photo } from './photo.entity';

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

  @Column()
  name: string;

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

#다대다 관계 만들기(many-to-many)

사진을 앨범 여러 개에 속할 수 있고, 앨범도 사진 여러 개를 가질 수 있다.

//album.entity.ts

import {
  Column,
  Entity,
  JoinTable,
  ManyToMany,
  PrimaryGeneratedColumn,
} from 'typeorm';
import { Photo } from './photo.entity';

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

  @Column()
  name: string;

  @ManyToMany(() => Photo, (photo) => photo.albums)
  @JoinTable()
  photos: Photo[];
}

#최종적인 테이블 구조

# MySQL 키 종류들

  1. Primary Key (고유키) 
    • NOT NULL & UNIQUE
    • 테이블 당 하나의 정의만 가질 수 있음
    • 여러 개가 PK로 지정되었다면 key 조합에 대한 유일성이 보장됨
  2. Unique Key 
    • NULL & UNIQUE
    • 테이블 당 여러개 가능
    • 복잡한 테이블에서 부분적인 정합성을 살리기 위해 많이 이용됨
  3. Foreign Key
    • 다른 DB와 관계를 맺을 때, 다른 테이블의 PK를 참조하는 컬럼(FK)
    • 서버의 안정성을 위해 지양하는 편
    • 제약 조건 옵션들(Constraint)
      1. RESTRICT : FK 관계를 맺고 있는 데이터 ROW 의 변경(UPDATE) 또는 삭제(DELETE) 를 막음
      2. CASCADE : FK 와 관계를 맺은 상대 PK 를 직접 연결해서 DELETE 또는 UPDATE 시, 상대 Key 값도 삭제 또는 갱신 
      3. SET NULL : 논리적 관계상 부모의 테이블, 즉 참조되는 테이블의 값이 변경 또는 삭제될 때 자식 테이블의 값을 NULL 만들음. UPDATE 쿼리로 인해 SET NULL 이 허용된 경우에만 동작
      4. NO ACTION : RESTRICT 옵션과 동작이 같지만, 체크를 뒤로 미룸
      5. SET DEFAULT : 변경 또는 삭제 시에 값을 DEFAULT 값으로 세팅
  4. Multiple Key
    • 중복 가능한 인덱스의 첫 번째 컬럼(보통은 FK, 여러 개의 컬럼을 묶어서 unique index를 구성한 경우)

 

참고자료