Open2

TypeORM 知見まとめ

Shinji NakashimaShinji Nakashima

TypeORMでSoft delete (論理削除)を実現する

前提 / 現状

  • すべてのEntityは、下記BaseEntityクラスを継承することで、 created_at, updated_at, deleted_at カラムを有している。
    BaseEntity.ts
    export default abstract class BaseEntity {
      @CreateDateColumn({ type: "datetime" })
      readonly created_at: Date;
      
      @Column({ type: "datetime", nullable: true, onUpdate: "CURRENT_TIMESTAMP" })
      readonly updated_at: Date;
      
      @Column({ type: "datetime", nullable: true })
      deleted_at: Date;
    }
    
  • 基本的にレコードの削除はSoft deleteで行う方針で、TypeORMの削除処理の代わりに someEntity.deleted_at = new Date(); なる処理を毎度書いている。

やりたいこと

  • わざわざ deleted_at カラムに値を代入する処理を書かずとも、Soft deleteを一発で実施したい。

解決策

TypeORMにはSoft deleteの機能が組み込まれているっぽい。

BaseEntity.ts
export default abstract class BaseEntity {
  @CreateDateColumn({ type: "datetime" })
  readonly created_at: Date;
  
  @UpdateDateColumn({ type: "datetime", nullable: true })
  readonly updated_at: Date;
  
  @DeleteDateColumn({ type: "datetime", nullable: true })  // 削除日時を自動代入
  readonly deleted_at: Date;
}
Soft delete処理
const deletedRecords = someEntity.find(/* 省略 */);  // 削除するレコードを抽出
someEntity.softRemove(deletedRecords);  // softRemoveだとrelation先のレコードも削除できる
Shinji NakashimaShinji Nakashima

TypeORM × MySQLでJSON型を使う

動機

  • これまで、1カラムに複数の値を持たせたいとき、複数レコード作成することで対応していた。
    • 例えば、会社テーブルで、会社毎の営業曜日を保持したいケース。
      • operatingDays = [1, 2, 3, 4, 5]
  • レコード数が多くなってしまうので、1会社1レコードにしたい。
    • となると、JSON型で配列を保持すればよいのでは?

解決策

TypeORMでJSON型を指定すると、MySQLのJSON型でカラムが作成される。
(PostgresSQLのJSONB型も対応しているらしい)

Company.ts
export default class Company extends BaseEntity {
  @Column({ type: "json" })  // JSON型を指定する
  operating_days: number[];  // JSON構造の型で宣言すればOK
}

実際にデータを取り出すと、JSONがパースされて返ってくるので、 JSON.parse などする必要は無い。
便利!