Help us understand the problem. What is going on with this article?

TypeORMのmigrationで作成されるテーブル名をカスタマイズする

More than 1 year has passed since last update.

はじめに

TypeORM、素晴らしいんですが、作成したモデルを元にmigrationを掛けると残念なことになります。

例えば、
モデル名 UserHoge → 作成されるテーブル名 user_hoge
プロパティ名 firstName → 作成されるカラム名 firstName

なんでテーブルはスネークケース、カラムはキャメルケースで連結なんだ :sob:

こうあってほしい

テーブル・カラム命名規約

Railsの規約がしっくり来るので、それ風にしたい。

  • テーブル名: モデルのスネークケース複数形 user_hoges
  • カラム名: スネークケース first_name

コード

とは言っても、rubyと違って(Type|Java)Scriptの変数命名規約がキャメルケースなので、
コード上はキャメルケースで書きたい

  • モデル名: キャメルケース単数 UserHoge
  • プロパティ名: キャメルケース firstName

うまい方法はないかと探した結果、上記は2通りの方法で実現できそうです。

[方法1] 個別でテーブル・カラム名を定義する

@Entityデコレーター、@Columnデコレーター共に、個別で名前を指定することができます。

@Entity('users') // これ!
export class User extends BaseEntity {
  @PrimaryGeneratedColumn()
  public id: number

  @Column({ name: 'first_name' }) // これ!
  public firstName: string = ''
}

これを元にmigrationを作成すると、指定した名前に応じたSQL文が発行されます。

これで、
「コード上はモデル名:User カラム名: firstName
「DB上はテーブル名:users カラム名: first_name

を実現できるわけですが、すべてのテーブル・カラムに個別に名前を付けていたのでは
ヌケモレが発生したとき大変なことになりますし、何より面倒くさいです。

[方法2] 名前付けルールを設定する

ormconfigに独自の名前付けルールを設定する事で、個別に名前を設定しなくても
自動的にORM⇔DB間でいい感じに変換してくれるようになります。

1. 設定ファイルを作成

ここではconfig/TypeOrmNamingStrategy.jsという名前で作ります。

やっていることは、公式が用意してるDefaultNamingStrategyを継承して、
ルールを書き換えただけです。(念の為、デフォルトのルールはこちら)

自分はモデルから作るテーブルの他に、多対多のリレーションの中間テーブルの名前等も変えてます。
他にもOverrideしたい場合は、適宜。

var DefaultNamingStrategy = require('typeorm').DefaultNamingStrategy
var snakeCase = require('typeorm/util/StringUtils').snakeCase
var pluralize = require('pluralize')

module.exports = class TypeOrmNamingStrategy extends DefaultNamingStrategy {
  tableName(className, customName) {
    return customName || pluralize(snakeCase(className))
  }

  columnName(propertyName, customName, embeddedPrefixes) {
    return snakeCase(embeddedPrefixes.join('_')) + (customName || snakeCase(propertyName))
  }

  relationName(propertyName) {
    return snakeCase(propertyName)
  }

  joinColumnName(relationName, referencedColumnName) {
    return snakeCase(pluralize.singular(relationName) + '_' + referencedColumnName)
  }

  joinTableName(firstTableName, secondTableName, firstPropertyName, secondPropertyName) {
    return snakeCase(firstTableName + '_' + secondTableName)
  }

  joinTableColumnName(tableName, propertyName, columnName) {
    return snakeCase(pluralize.singular(tableName) + '_' + (columnName || propertyName))
  }

  classTableInheritanceParentColumnName(parentTableName, parentTableIdPropertyName) {
    return snakeCase(pluralize.singular(parentTableName) + '_' + parentTableIdPropertyName)
  }
}

2. ormconfigを編集する

先程作ったカスタム名前付けルールのクラスを読み込むようにします。
設定内でクラスをインスタンス化しているため、ormconfig.jsonでは駄目です。
json拡張子を使っている人は、ormconfig.jsに変更してください。

ormconfig.js
const TypeOrmNamingStrategy = require('./src/configs/TypeOrmNamingStrategy.js') // これ!

module.exports = {
  // 色々独自の設定
  type: 'postgres',
  host: process.env.DB_HOSTNAME,
  port: 5432,
  username: process.env.DB_USERNAME,
  password: process.env.DB_PASSWORD,
  ...
  namingStrategy: new TypeOrmNamingStrategy() // これ!!
}

3. いつも通りmigrationを当てる

カスタムルールに基づいた命名規則でmigrationが作られるようになります。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away