2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

TypeORM でハマったところを書いておく

Last updated at Posted at 2021-08-27

ormconfig は .json ではなく .js または .ts にしたほうが便利

デフォルトだと ormconfig.json ファイルが生成されるけど、ファイルフォーマットは選べる。
https://typeorm.io/#/using-ormconfig/creating-a-new-connection-from-the-configuration-file

で、ormconfig にデータベースの接続情報を書くけど、直書きしたくはないので、.jsとしておくと
以下のように環境変数を読めるので、便利!

ormconfig.js
module.exports = {
  'type': 'mysql',
  'host': process.env['MYSQL_HOST'] || 'localhost',
  'port': process.env['MYSQL_PORT'] || 3306,
  'username': process.env['MYSQL_USER'] || 'username',
  'password': process.env['MYSQL_PASSWORD'] || 'password',
  'database': process.env['MYSQL_DATABASE'] || 'database',
  ...
};

synchronize オプションは false (デフォルト false なので設定しないでよい)

ドキュメントにある通り、synchronize オプションを true にすると、Entity の設定がデータベースに反映されちゃう。
Entity にリレーション設定をしてると、外部キーカラムが勝手に追加されたりする。
急に Migration に書いてない userId カラムが増えてて「は?」ってなった。

Setting synchronize makes sure your entities will be synced with the database, every time you run the application.

命名規則が Laravel の Migration と違う

Laravel の Migration からインスピレーションを受けた的なことがライブラリの説明に書いてあった気がしまして、
勝手に命名規則は同じものを思ってたらそうじゃなかった。
例えば Laravel はテーブル名は複数形、Entity(EloquentModel) は単数形だけど、TypeORM そうなってない。
TypeORM の命名規則は DefaultNamingStrategy にあって継承することでカスタマイズは可能とのこと。

参考1
参考2
参考3

追記
テーブル名を複数、Entity名を単数にする場合は、@Entity() の引数にテーブル名を渡せば良い。
カラム名をスネークケース、プロパティ名をキャメルケースにする場合は、@Column() の option の name プロパティにカラム名を指定してあげれば良いみたいです!

@Entity('hoges')
export class Hoge {

    @PrimaryGeneratedColumn()
    id!: number;

    @Column({type: 'varchar', name: 'column_name', nullable: false})
    columnName!: string;
}

isPrimary: true だけだと auto increment じゃないっぽい

Migration でサンプル通り id カラムに isPrimary: true を指定したら当然 auto increment になると思ってたけど、そうじゃなかった。
Field 'id' doesn't have a default value? って言われる。
なので、isGenerated: truegenerationStrategy: 'increment'を指定する。
参考

import {MigrationInterface, QueryRunner, Table, TableIndex, TableColumn, TableForeignKey } from "typeorm";

export class QuestionRefactoringTIMESTAMP implements MigrationInterface {

    async up(queryRunner: QueryRunner): Promise<void> {
        await queryRunner.createTable(new Table({
            name: "question",
            columns: [
                {
                    name: "id",
                    type: "int",
                    isPrimary: true,
                    isGenerated: true,
                    generationStrategy: 'increment'
                },
                {
                    name: "name",
                    type: "varchar",
                }
            ]
        }), true)

    }

    async down(queryRunner: QueryRunner): Promise<void> {
        await queryRunner.dropTable("question");
    }

}

docker-compose を使う場合、host 名はDBコンテナ名

TypeORM に直接関係ないけど。
https://qiita.com/kajirikajiri/items/c2b557d884689a2b851e

nullable カラムの Entity プロパティ指定方法

Entity から Migration を作るコマンドがおそらくある

たぶんある。先にマイグレーションを書いたのでちゃんと確認してない。

Cannot use import statement outside a module

EntityMetadataNotFound: No metadata for “Hoge” was found

テーブル名とEntity名があってない(命名規則に則ってない)とか、コンパイル後のファイルが指定箇所以外に残ってるとかでこのエラーは解消できた気がする。

connection が生成できない

default がなんちゃらで connenction が生成できなかった。
keepConnectionAlive オプションを true 指定すれば良いとか見たけど。うまく行かなかった。
以下の実装で回避できた。

const connection = async (): Promise<Connection> => {
    try {
        return await getConnection();
    } catch (error) {
        return await createConnection();
    }
};

const connection = await connection();
2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?