TypeORM で created_at・updated_at カラムを作る

TypeORM + PostgreSQL の組み合わせで、「レコードを新規登録した日時」と「レコードを最後に更新した日時」のカラムを自動設定できるようにする。

import { CreateDateColumn, Entity, PrimaryColumn, UpdateDateColumn } from 'typeorm';

/** 顧客情報 */
@Entity('my_customers')
export default class MyCustomer {
  /** 氏名 */
  @PrimaryColumn({ name: 'user_name', type: 'varchar' })
  userName: string;
  
  /** 新規登録日時 */
  @CreateDateColumn({ name: 'created_at', type: 'timestamp', precision: 0 })
  readonly createdAt: Date;
  
  /** 最終更新日時 */
  @UpdateDateColumn({ name: 'updated_at', type: 'timestamp', precision: 0 })
  readonly updatedAt: Date;
}

こんな感じ。

precision: 0 で日時の精度を 0 にし、ミリ秒以下が6桁分くらい記録されないようにしている。

save()update() メソッドなどで DB 登録する時は、日時カラムは指定しなくて良いが、find() で取得すると値が入って返ってくる。

const myCustomerRepository = getRepository(MyCustomer);

// save() = UPSERT
await myCustomerRepository.save({ userName: 'HOGE' });

// update() = 明示的な Update : ユーザ名が Foo なレコードを対象に、Bar へ変更する
await myCustomerRepository.update({ userName: 'Foo' }, { userName: 'Bar' });

// find() = SELECT : created_at・updated_at が拾える
const myCustomers = await myCustomerRepository.find();

save() メソッドの挙動について注意点があって、値の更新が一切発生しない場合は Update 自体が発生しないので、updated_at カラムが更新されないことに注意。

一方 update() メソッドの場合は必ず UPDATE が流れるので、実質的に値が変わっていなくても、updated_at の値が更新される。