[TypeORM] Relation

hahaha·2021년 11월 6일
1

TypeORM

목록 보기
3/4

Relation

options

  • eager
  • cascade
    - cascade: boolean | ("insert" | "update")[]
    - true, the related object will be inserted and updated in the database.
  • onDelete
  • primary
  • nullable
  • orphanedRowAction

cascades

  • example
@Entity()
export class Category {

    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    name: string;

    @ManyToMany(type => Question, question => question.categories)
    questions: Question[];

}

@Entity()
export class Question {

    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    title: string;

    @Column()
    text: string;

    @ManyToMany(type => Category, category => category.questions, {
        cascade: true // -> cascade option 설정
    })
    @JoinTable()
    categories: Category[];

}

const category1 = new Category();
category1.name = "ORMs";

const category2 = new Category();
category2.name = "Programming";

const question = new Question();
question.title = "How to ask questions?";
question.text = "Where can I ask TypeORM-related questions?";
question.categories = [category1, category2];
await connection.manager.save(question);
  • casecade: true
    -> category1, category2에 대해 save 메소드를 호출하지 않아도 자동으로 insert 수행
  • "great power comes with great responsibility"
    - 버그나 보안상 이슈가 발생할 수 있음

cascade options

  • insert, update, remove, soft-remove, recover, etc.
  • 설정된 옵션의 기능이 save 메소드를 호출할 때 자동으로 수행 됨
  • ex. casecade: ['insert', 'update']

@JoinColumn

  • @OneToOne 에는 필수
  • FK, PK가 아닌 컬럼의 경우 원칙적으로 불가능
  • propertyName + referencedColumnName로 자동 생성
@ManyToOne(type => Category)
@JoinColumn() // -> 'categoryId' 컬럼 생성됨
category: Category;
  • 조인 컬럼의 이름을 지정할 수 있음
@ManyToOne(type => Category)
@JoinColumn({ name : 'cat_id' })
category: Category;
  • default: 연관된 엔티티의 FK를 이용해 참조
  • 연관된 엔티티의 다른 컬럼 참조도 가능
    - referencedColumnName 이용
@ManyToOne(type => Category)
@JoinColumn({ referencedColumnName: "name" }) // Category의 PK인'id'가 아닌 'name' 컬럼을 참조
category: Category;
  • 여러 개의 조인 컬럼 지정 가능
    - 반드시 referencedColumnName 설정해야 함
@ManyToOne(type => Category)
@JoinColumn([
    { name: "category_id", referencedColumnName: "id" },
    { name: "locale_id", referencedColumnName: "locale_id" }
])
category: Category;

@JoinTable

  • @ManyToMany 에서 사용
  • juction 테이블의 컬럼을 설명
    - juction table: 연관된 엔티티를 참조하는 컬럼으로 구성되어 TypeORM에 의해 자동 생성된 테이블
@ManyToMany(type => Category)
@JoinTable({
    name: "question_categories", // table name for the junction table of this relation
    joinColumn: {
        name: "question",
        referencedColumnName: "id"
    },
    inverseJoinColumn: {
        name: "category",
        referencedColumnName: "id"
    }
})
categories: Category[];

@OneToOne

  • @OneToOne, @JoinColumn 한 쪽에만 선언 (uni-directional)
    - 선언된 쪽의 DB 테이블에 FK가 반드시 존재해야 함
  • bi-directional 생성 시, 양쪽에 @OneToOne 선언
    - 두 쪽 모두에서 관계를 조인할 수 있음
    • @JoinColumn 한 쪽에만

@OneToMany, @ManyToOne

  • @JoinColumn 생략 가능
  • @OneToMany사용 시, @ManyToOne 필수
    - 반대로@ManyToOne 사용 시, @OneToMany 필수 X (@ManyToOne 단독 사용 가능)

@ManyToMany

  • @JoinTable 사용
    - 한 쪽에만 사용

Eager and Lazy Relations

Eager

  • eager relation 자동 로드
    - 조인하지 않아도 find 할 경우, 연관된 관계가 자동으로 로드되어 짐(자동 조인의 개념)
    - find 메소드에서만 작동
  @ManyToMany(type => Category, category => category.questions, {
        eager: true
    })
    @JoinTable()
    categories: Category[];

Lazy Relations

  • 접근할 때 로드됨
  • Promise 타입을 가짐
@ManyToMany(type => Question, question => question.categories)
    questions: Promise<Question[]>;

@ManyToMany(type => Category, category => category.questions)
    @JoinTable()
    categories: Promise<Category[]>;

self referencing relation

@Entity()
export class Category {

    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    title: string;

    @Column()
    text: string;

    @ManyToOne(type => Category, category => category.childCategories)
    parentCategory: Category;

    @OneToMany(type => Category, category => category.parentCategory)
    childCategories: Category[];

}

Find

1. FindOptions

  • where절 relations option 사용
const userRepository = connection.getRepository(User);
const users = await userRepository.find({ relations: ['photos']});

2. QueryBuilder

  • join 사용
const users = await connection
	.getRepository(User)
	.createQueryBuilder('user')
	.leftJoinAndSelect('user.photos', 'photo')
	.getMany();
profile
junior backend-developer 👶💻

2개의 댓글

comment-user-thumbnail
2022년 8월 11일

This post is easy to read and appreciate without leaving out any details. Excellent work!
@geometry dash

답글 달기
comment-user-thumbnail
2022년 12월 15일

This article is simple to read and enjoyable, without omitting any of the important details. word finder

답글 달기