ormconfig は .json ではなく .js または .ts にしたほうが便利
デフォルトだと ormconfig.json
ファイルが生成されるけど、ファイルフォーマットは選べる。
https://typeorm.io/#/using-ormconfig/creating-a-new-connection-from-the-configuration-file
で、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 にあって継承することでカスタマイズは可能とのこと。
追記
テーブル名を複数、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: true
と generationStrategy: '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();