본문 바로가기

TIL/ChoLog

주니어개발자 앱개발기4 - Types + TypeORM 사용하기

res.json() vs res.send() vs res.end() in Express: https://blog.fullstacktraining.com/res-json-vs-res-send-vs-res-end-in-express/

 

Typescript + TypeORM 사용하기

아래는 @types/entity/index.ts 파일.

declare namespace entity {
  interface plantsDatabaseType {
    distributionName: string; // distributionName는 plantsDatabaseType에 필수적으로 있어야 하는 key값이다.
    scientificName?: string; // scientificName은 key값 뒤에 '?'가 붙어있기 때문에 없어도 된다.
    englishName?: string;
  }

  interface apiType { // 이번 예제(?)에서 사용하지 않음
    provider: string;
    url: string;
  }
}

export = entity;

@types는 코드에서 사용할 interface들을 한번에 저장해 둔 디렉토리이다.

타입관리를 편하게 하기 위해 생성했다.

 

아래는 entity/PlantsDatabase.ts

import {
  Entity,
  BaseEntity,
  PrimaryGeneratedColumn,
  Column,
  CreateDateColumn,
  UpdateDateColumn,
} from "typeorm";
import { plantsDatabaseType } from "../@types/entity";

@Entity()
export default class PlantsDatabase extends BaseEntity {
  @PrimaryGeneratedColumn({ unsigned: true })
  id!: number;

  @Column()
  distributionName!: string; // 유통명

  @Column({ nullable: true, unique: true })
  scientificName!: string; // 학명

  @Column({ nullable: true })
  englishName!: string;

  @CreateDateColumn({ name: "created_at", type: "timestamp" })
  public createdAt!: Date;

  @UpdateDateColumn({ name: "updated_at", type: "timestamp" })
  public updatedAt!: Date;

  //* 데이터 입력
  // 아래의 findOrCreatePlantData는 plantsDatabaseType를 파라미터로 사용하고 있다.
  // plantsDatabaseType는 distributionName은 필수로 포함하고 있고, scientificName과 englishName은 있을수도 있고 없을수도 있는 객체이다.
  static async findOrCreatePlantData(
    data: plantsDatabaseType,
  ): Promise<PlantsDatabase | undefined> {
    const { scientificName } = data;
    if (scientificName) { // scientificName은 필수적으로 입력되는 데이터가 아니기 때문에 존재여부를 확인해야 한다.
      //! 동일한 학명을 가진 식물data가 있는지 확인
      findPlant = await this.findOne({ scientificName });
      if (findPlant) {
        return findPlant;
      }
    }

    const { id } = (
      await this.createQueryBuilder()
        .insert()
        .into(PlantsDatabase)
        .values(data)
        // insert into의 values의 값을 data(:plantsDatabaseType)로 줄 경우 data가 가지고있는 값만 데이터에 추가된다.
        // data가 가지고 있지 않은 값은 entity설정의 default값으로 입력된다.
        .execute()
    ).identifiers[0];

    return this.findOne({ id });
  }
}

위 findOrCreatePlantData메서드에서 insert into의 values에 data를 집어넣어 원하는 값만 지정하고 나머지는 default값으로 데이터를 저장할 수 있듯이

update문에서도 위와 같이 사용하면 원하는 데이터만 업데이트할 수 있다.

 

위 엔티티를 사용하는 방법

import PlantsDatabase from "./entity/PlantsDatabase";
import { plantsDatabaseType } from "../@types/entity";

const plantData: plantsDatabaseType = {
  distributionName: "황금마삭줄",
  scientificName: "Trachelospermum asiaticum var. variegatum",
} // distributionName을 제외한 나머지 값은 필수요소가 아니기 때문에 있어도 되고 없어도 됨
const newPlantDatabase = await PlantsDatabase.createQueryBuilder(plantData);
console.log(newPlantDatabase);
/* 위 콘솔의 실행 결과
PlantsDatabase {
  id: 1,
  distributionName: "황금마삭줄",
  scientificName: "Trachelospermum asiaticum var. variegatum",
  englishName: null,
  createdAt: 2020-02-18T12:22:13.208Z,
  updatedAt: 2020-02-18T12:22:13.208Z,
}
*/