entity relation(user, restaurant, category)

김종민·2022년 6월 29일
0

Nuber-Server

목록 보기
15/34

들어가기
entity(user, restaurant, category)를
정리해 본다.
entity간의 관계가 엮이는 것에 대해서 중점적으로
알아본다,

@OneToMany() : 일대 다 관계
@ManyToOne() : 다대 일 관계

Relation options
onDelete:'RESTRICT'|'CASCADE'|'SET NULL'
참조된 객체가 삭제될 때, 외래 키가 어떻게 작동하는지 지정한다.
https://orkhan.gitbook.io/typeorm/docs/relations#relation-options

1.users/entities/user.entity.ts

import {
  Field,
  InputType,
  ObjectType,
  registerEnumType,
} from '@nestjs/graphql';
import { CoreEntity } from 'src/common/entities/core.entity';
import { Column, Entity, BeforeInsert, BeforeUpdate, OneToMany } from 'typeorm';
import * as bcrypt from 'bcrypt';
import { InternalServerErrorException } from '@nestjs/common';
import { IsEmail, IsEnum, IsString } from 'class-validator';
import { Restaurant } from 'src/restaurant/entities/restaurant.entity';

export enum UserRole {
  Client = 'Client',
  Owner = 'Owner',
  Delivery = 'Delivery',
}

registerEnumType(UserRole, { name: 'UserRole' });

@InputType('UserInputType', { isAbstract: true })
///InputType안에 ''를 달아주는 이유는 고유의 이름을 가져야
///schema unique 충돌을 피할 수 있다!! 매우중요

@ObjectType()
@Entity()
export class User extends CoreEntity {
  @Column({ unique: true })
  @Field(() => String)
  @IsEmail()
  email: string;

  @Column()
  @Field(() => String)
  @IsString()
  password: string;

  @Column({ type: 'enum', enum: UserRole })
  @Field(() => UserRole)
  @IsEnum(UserRole)
  role: UserRole;
  
  *************************************************************

  @Field(() => [Restaurant])
  @OneToMany(() => Restaurant, (restaurant) => restaurant.owner)
  restaurants: Restaurant[];
  ///한명의 user는 다수의 restaurant를 가질 수 있다.
********************************************************************

  @BeforeInsert()
  @BeforeUpdate()
  async hashPassword(): Promise<void> {
    try {
      this.password = await bcrypt.hash(this.password, 10);
    } catch (e) {
      console.log(e);
      throw new InternalServerErrorException();
    }
  }

  async checkPassword(aPassword: string): Promise<boolean> {
    try {
      const ok = await bcrypt.compare(aPassword, this.password);
      return ok;
    } catch (e) {
      console.log(e);
      throw new InternalServerErrorException();
    }
  }
}

2. restaurant/entities/restaurant.entity.ts


import { Field, InputType, ObjectType } from '@nestjs/graphql';
import { Entity, Column, ManyToOne, RelationId } from 'typeorm';
import { IsString, Length } from 'class-validator';
import { CoreEntity } from 'src/common/entities/core.entity';
import { Category } from './category.entity';
import { User } from 'src/users/entities/user.entity';

@InputType('RestaurantInputType', { isAbstract: true })
///InputType안에 ''를 달아주는 이유는 고유의 이름을 가져야
///schema unique 충돌을 피할 수 있다!! 매우중요

@ObjectType()
@Entity()
export class Restaurant extends CoreEntity {
  @Field(() => String)
  @Column()
  @IsString()
  @Length(5)
  name: string;

  @Field(() => String)
  @Column()
  @IsString()
  coverImg: string;

  @Field(() => String)
  @Column()
  @IsString()
  address: string;

*********************************************************************
  @Field(() => Category, { nullable: true })
  @ManyToOne(() => Category, (category) => category.restaurants, {
    nullable: true,
    onDelete: 'SET NULL',
  })
  category: Category;
  ///여러개의 restaurant가 하나의 category를 가진다. category가 
  ///없어도 가능하며(nullable: true), category를 지워도, 
  ///관련된, restaurant는 지워지지 않는다.(onDelete: 'SET NULL')

  @Field(() => User)
  @ManyToOne(() => User, (user) => user.restaurants, { onDelete: 'CASCADE' })
  owner: User;
  ///여러개의 식당이 한명의 user를 가질 수 있다. owner의 type은 User
  ///owner를 delete하면, 관련된 restaurant가 사라진다(onDelete:'CASCADE')

  @RelationId((restaurant: Restaurant) => restaurant.owner)
  ownerId: number;
  ///restaurant의 owner의 id를 ownerId로 RelationId로 만들어준다.
}
******************************************************************

3. restaurant/entities/category.entity.ts

import { Field, InputType, ObjectType } from '@nestjs/graphql';
import { IsString, Length } from 'class-validator';
import { CoreEntity } from 'src/common/entities/core.entity';
import { Column, Entity, OneToMany } from 'typeorm';
import { Restaurant } from './restaurant.entity';

@InputType('CategotyInputType', { isAbstract: true })
///InputType안에 ''를 달아주는 이유는 고유의 이름을 가져야
///schema unique 충돌을 피할 수 있다!! 매우중요

@ObjectType()
@Entity()
export class Category extends CoreEntity {
  @Field(() => String)
  @Column({ unique: true })
  @IsString()
  @Length(5)
  name: string;

  @Field(() => String, { nullable: true })
  @Column({ nullable: true })
  @IsString()
  coverImg: string;

  @Field(() => String)
  @Column({ unique: true })
  @IsString()
  slug: string;

*****************************************************************
  @Field(() => [Restaurant], { nullable: true })
  @OneToMany(() => Restaurant, (restaurant) => restaurant.category)
  restaurants: Restaurant[];
  ///category entity는 restaurants column을 가짐,
  ///카테고리는 여러개의 식당을 가질 수 있기 떄문에, 배열로 정의한다.
  ///graphql은 [Restaurant]로, typeOrm은 Restaurant[], 로 정의
  *****************************************************
}
  1. Entity간의 관계를 이어주는 방법은 매우 중요하므로, nestJs, typeOrm에서 관계로
    엮어주는 방법을 잘 기억해 좋는다.
profile
코딩하는초딩쌤

0개의 댓글