【初心者用メモ】TypeORM / PostgreSQL で One-To-Many relation を定義する


はじめに

TypeORMを勉強していたときのメモです。

セットアップ

こちらを参照

mkdir sample && cd sample
npx typeorm init --database postgres --express --docker
yarn

One-To-Many relation

一人のユーザにいくつもの写真データが紐付いている場合を考えます。

Entityの定義

src/entity/User.ts
import {
  Entity,
  PrimaryGeneratedColumn,
  Column,
  OneToMany,
  BaseEntity,
} from 'typeorm';
import { Photo } from './Photo';

@Entity()
export class User extends BaseEntity { // extendしないとUser.createメソッドが使えない
  @PrimaryGeneratedColumn()
  readonly id: number;

  @Column()
  name: string;

  @OneToMany((type) => Photo, (photo) => photo.user) // これはフォールドでなく、relationを表現しているだけ
  photos: Photo[];
}
src/entity/Photo.ts
import {
  Entity,
  PrimaryGeneratedColumn,
  Column,
  ManyToOne,
  JoinColumn,
  BaseEntity,
} from 'typeorm';
import { User } from './User';

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

  @Column()
  url: string;

  @Column()
  userId: number;

  @ManyToOne((type) => User, (user) => user.photos) // relationを表現しているだけで、fieldとはならない
  @JoinColumn({ name: 'userId' }) // userIdがforeignキーとなることを表す。
  user: User;
}

Controllerの実装

ここで、UserContollerで新しいリクエストがきた時の処理を例として考える

src/controller/UserController.ts

...

  async save(request: Request, response: Response, next: NextFunction) {
    const { name, url } = request.body;
    const user = await User.find({ where: { name } });
    if (user.length) {
      //すでにユーザーが登録済の場合
      await Photo.create({ url, userId: user[0].id }).save();
    } else {
      //ユーザーが未登録の場合
      const newUser = await User.create({ name }).save();
      const newPhoto = await Photo.create({ url, userId: newUser.id }).save();
    }

    return await getConnection() // ormconfig.jsonで定義したDBに接続する。今回はpostgresだけだが、複数のDBに接続している場合は、今回接続するDB名を第一引数にを明示する
      .createQueryBuilder(User, 'u') // 第一引数はテーブル名、第二引数はそのalias
      .leftJoinAndSelect('u.photos', 'photo')
      .getMany();
  }

...

こんな感じで返ってくる

参考

https://youtu.be/ao4C9dJO7n0
https://typeorm.io/#/many-to-one-one-to-many-relations