データベース

TypeORMとは?1.1系の使い方|エンティティ・リレーション・マイグレーションを実行して解説

TypeORMとは?1.1系の使い方|エンティティ・リレーション・マイグレーションを実行して解説

TypeORMは、TypeScriptのクラスとデコレーターでテーブルを定義し、SQLを書かずにデータベースを読み書きできるNode.js向けのORM(オブジェクト関係マッピング)ライブラリです。2026年5月19日に1.0が公開され、長く非推奨だった Connection 系のAPIや sqlite3 ドライバが削除されました。2026年9月時点のnpmの最新版は1.1.1で、各版の変更内容はGitHubのリリース一覧で確認できます。0.3系の情報をもとに書いたコードは、1.x系ではそのまま動かないことがあります。

この記事では、TypeORM 1.1.1を実際にインストールし、エンティティ定義、リレーション、マイグレーション、QueryBuilder、トランザクションまでを動かした手順を、そのときのコードと出力つきで説明します。検証環境はNode.js v26.5.0、TypeScript 7.0.2、better-sqlite3 12.11.1です。

まとめ:TypeORMの位置づけと1.x系で押さえる要点

  • 何をするものか:TypeScriptのクラスをテーブルに対応させるORMです。Data MapperとActive Recordの両方の書き方に対応しています。
  • 最新版:npmのlatestは1.1.1(2026年9月1日公開)です。0.3系は legacy タグで0.3.31まで保守されています。
  • 1.0の破壊的変更:Node.js 20以上が必須になり、createConnection などのグローバル関数、sqlite3 ドライバ、TYPEORM_* 環境変数による設定が削除されました。
  • 実行時に効く変更:where条件に null や undefined を渡すと、無視されずに例外が出るようになりました。null判定は IsNull() で書きます。
  • 本番のスキーマ変更:synchronize: true は使わず、マイグレーションを生成して適用します。

以下、定義と特徴から順に、動かしたコードを交えて解説します。

TypeORMの定義と特徴

TypeORMはMITライセンスのオープンソースで、GitHubのスター数は2026年9月時点で約3万7,000です。クラスに @Entity() を付けるとテーブル、プロパティに @Column() を付けるとカラムになります。取得結果はそのクラスのインスタンスとして返るため、エディタの補完と型チェックがそのまま効きます。ORMという仕組み全般の説明は省き、ここではTypeORMならではの特徴に絞ります。

Data MapperとActive Recordの両対応

Data Mapper方式では、エンティティはデータを持つだけのクラスにして、保存や検索は dataSource.getRepository(User) で取得したリポジトリから呼びます。Active Record方式では、エンティティが BaseEntity を継承し、User.find() や user.save() のようにクラス自身が操作メソッドを持ちます。公式ドキュメントは、Data Mapperは大規模なアプリの保守性に、Active Recordは小規模なアプリの簡潔さに向くと説明しています。テストでリポジトリを差し替えたい場合や、NestJSで依存性注入を使う場合はData Mapperを選ぶのが無難です。この記事のコードもData Mapperで書いています。

対応データベースとドライバ

1.1.1の package.json では、次のドライバがオプションの依存(peerDependencies)として宣言されています。使うデータベースのドライバだけを追加でインストールします。

データベース DataSourceのtype ドライバと対応版
PostgreSQL postgres pg ^8.5.1
MySQL・MariaDB mysql mysql2 ^3.15.3
SQLite better-sqlite3 better-sqlite3 ^12.0.0
SQL Server mssql mssql ^12.0.0
Oracle oracle oracledb ^6.3.0 または ^7.0.0
MongoDB mongodb mongodb ^7.0.0

このほかSAP HANA、Google Cloud Spanner、ブラウザ向けのsql.jsにも対応しています。MySQLの旧クライアント mysql は1.0で対象外になり、mysql2 だけが使えます。

TypeORM 1.0で変わった点と0.3系からの移行

1.0は、0.3系で非推奨になっていたAPIをまとめて削除したリリースです。公式の移行ガイド(Upgrading from 0.3 to 1.0)から、影響を受けやすいものを抜き出しました。

0.3系の書き方 1.x系での扱い
Node.js 16・18 非対応(Node.js 20以上)
createConnection・getConnection 削除。new DataSource()を使う
Connection・ConnectionOptions型 削除。DataSource・DataSourceOptions
TYPEORM_URLなどの環境変数、ormconfig.env 削除。TS・JSの設定ファイルで書く
type: "sqlite" 削除。type: "better-sqlite3"
findByIds([1, 2, 3]) 削除。findBy({ id: In([1, 2, 3]) })
exist() exists()に改名
@EntityRepository・getCustomRepository 削除。Repository.extend()
findのjoinオプション 削除。relationsかQueryBuilder
文字列配列のselect・relations 削除。オブジェクト形式で書く

TypeORMは .env ファイルを自動で読み込まなくなり、dotenv への依存もなくなりました。接続情報を環境変数から渡す場合は、設定ファイルの中で process.env を自分で参照します。

where条件のnull・undefinedが例外になる変更

移行ガイドが「実行時に既存のアプリを壊しうる大きな変更」と明記しているのが、invalidWhereValuesBehavior の既定値の変更です。0.3系では findBy({ id: undefined }) のようにundefinedを渡すと条件が黙って無視され、全件が返っていました。1.x系ではnullとundefinedのどちらも例外になります。検証コードで findBy({ nickname: undefined }) を実行すると、次の出力になりました。

TypeORMError Undefined value encountered in property 'User.nickname' of a where condition. Set 'invalidWhereValuesBehavior.undefined' to 'ignore' in connection options to skip properties with undefined values.

NULLの行を探すときは IsNull() 演算子を使います。検索フォームの未入力項目をそのままwhereに渡しているコードは、この変更で例外を出すようになります。その項目で絞り込まない場合は、条件を組み立てる側で項目をオブジェクトから除いてください。未入力を IsNull() に置き換えると、NULLの行だけを探す別の検索になります。どうしても旧挙動に戻す場合は、DataSourceに次の設定を加えます。

new DataSource({
    // ...
    invalidWhereValuesBehavior: {
        null: "ignore",
        undefined: "ignore",
    },
})

この設定の対象はfind系メソッド、リポジトリとEntityManagerの更新系メソッド、setFindOptions() です。QueryBuilderの .where() には影響しません。また1.1.0からは、update() や delete() に空の条件を渡すと拒否されます。検証では update({}, { title: "x" }) が Empty criteria(s) are not allowed for the update method. で止まりました。条件の渡し忘れによる全件更新を防ぐための変更です。

codemodによる自動移行とNestJSの対応版

公式の @typeorm/codemod を使うと、importの書き換え、APIの置き換え、findオプションの書式変更、依存パッケージの更新を自動で行えます。--dry を付けると、ファイルを書き換えずに変更内容だけを確認できます。自動化できない箇所には TODO コメントが残ります。

npx @typeorm/codemod v1 src/

NestJSで @nestjs/typeorm を使っている場合、v10とv11.0.0は起動時に削除済みの Connection クラスを登録しようとして落ちます。移行ガイドはv11.0.1以降への更新を求めています。2026年9月時点の最新版は12.0.1で、peerDependenciesは typeorm: ^0.3.0 || ^1.0.0-dev です。

TypeORM 1.1.1のインストールと初期設定

1.1.1が求めるNode.jsは ^20.19.0 || ^22.13.0 || >=24.11.0 です。Node.jsの版の選び方はNode.jsの仕組みと版の選び方で整理しています。

パッケージの導入

本体、デコレーターのメタデータを扱う reflect-metadata、使うデータベースのドライバを入れます。検証ではSQLiteを使いました。

npm install [email protected] [email protected] [email protected]
npm install -D [email protected] @types/[email protected]

版は検証時のものに固定しています。npm 11.17.0では、better-sqlite3のインストール時に、allowScripts で承認されていないインストールスクリプトがあるという npm warn allow-scripts の警告が出ました。検証ではこの警告が出た状態でもネイティブモジュールはビルドされ、ドライバを読み込めました。警告を消すには npm approve-scripts better-sqlite3 で承認し、package.json の allowScripts に記録します。

エディタで Cannot find module 'typeorm' or its corresponding type declarations. が出る場合は、typeormが node_modules に入っているか、tsconfig.jsonの module の設定とimportの書き方が合っているかを確認します。

tsconfig.jsonの必須オプション

デコレーターを使うため、experimentalDecorators と emitDecoratorMetadata を有効にします。TypeScript 7.0.2でコンパイルするには、TypeORMの公式手順に載っていない設定が3つ必要でした。1つ目は rootDir で、指定しないとエラーTS5011で止まります。2つ目は types: ["node"] で、指定しないとTypeORMの型定義の中で Buffer や tls が見つからないというエラーが出ます。3つ目は lib の ESNext.Disposable で、AsyncDisposable が見つからないというエラーを解消します。skipLibCheck で型定義のエラーをまとめて抑える方法もありますが、検証では使わずに次の設定でコンパイルを通しました。

{
  "compilerOptions": {
    "target": "ES2023",
    "module": "commonjs",
    "rootDir": "src",
    "outDir": "dist",
    "strict": true,
    "strictPropertyInitialization": false,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "lib": [
      "ES2023",
      "ESNext.Disposable"
    ],
    "types": [
      "node"
    ]
  },
  "include": [
    "src"
  ]
}

strictPropertyInitialization を無効にしているのは、エンティティのプロパティに初期値を書かないためです。有効のまま使う場合は、各プロパティに ! を付けます。

DataSourceの設定ファイル

接続設定は DataSource のインスタンスとして書き、アプリとCLIの両方から読み込みます。

import "reflect-metadata"
import { DataSource } from "typeorm"
import { User } from "./entities/User"
import { Post } from "./entities/Post"

export const AppDataSource = new DataSource({
    type: "better-sqlite3",
    database: "app.sqlite",
    entities: [User, Post],
    migrations: ["dist/migrations/*.js"],
    synchronize: false,
    logging: ["query", "error"],
})

ファイルの配置は src/data-source.ts、src/entities/User.ts、src/entities/Post.ts です。logging に "query" を入れると、発行されたSQLがそのまま出力されます。以降の章のSQLは、この設定で記録したものです。

エンティティ定義で使うデコレーター

ユーザーと投稿の2テーブルを定義します。

import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, OneToMany } from "typeorm"
import { Post } from "./Post"

@Entity()
export class User {
    @PrimaryGeneratedColumn()
    id: number

    @Column({ length: 100, unique: true })
    email: string

    @Column({ type: "varchar", nullable: true })
    nickname: string | null

    @CreateDateColumn()
    createdAt: Date

    @OneToMany(() => Post, (post) => post.author)
    posts: Post[]
}
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne } from "typeorm"
import { User } from "./User"

@Entity()
export class Post {
    @PrimaryGeneratedColumn()
    id: number

    @Column()
    title: string

    @Column({ default: false })
    published: boolean

    @ManyToOne(() => User, (user) => user.posts, { nullable: false })
    author: User
}

ここで使ったデコレーターと、実際に生成されたDDLの対応は次のとおりです。

デコレーターとオプション SQLiteで生成された定義
@PrimaryGeneratedColumn() integer PRIMARY KEY AUTOINCREMENT NOT NULL
@Column({ length: 100, unique: true }) varchar(100) NOT NULL + UNIQUE制約
@Column({ type: "varchar", nullable: true }) varchar(NULL許可)
@Column({ default: false }) boolean NOT NULL DEFAULT (0)
@CreateDateColumn() datetime NOT NULL DEFAULT (datetime(‘now’))
@ManyToOne(..., { nullable: false }) authorId integer NOT NULL + 外部キー

@Column() は、オプションを省くとNOT NULLになります。NULLを許すカラムは nullable: true を明示してください。string | null のようなユニオン型は、デコレーターのメタデータから列の型を推定できません。そのため type も指定しています。type を省くと、初期化時に DataTypeNotSupportedError(Data type "Object" in "User.displayName" is not supported by "better-sqlite3" database.)で止まりました。

エンティティはDataSourceの entities に登録します。登録を忘れたクラスでクエリを実行すると、EntityMetadataNotFoundError が出ます(検証時のメッセージは No metadata for "Tag" was found.)。entities にglobパターンで .ts を指定したまま、コンパイル後の .js で起動した場合もこのエラーになります。NestJSでAPIの入出力にエンティティを直接使わず、DTOを分けて定義する考え方はNestJSにおけるDTOの基本で扱っています。

リレーションの設定方法

リレーションは、片方のエンティティだけにデコレーターを付ける単方向と、両方に付けて互いに参照できる双方向のどちらでも定義できます。1対1と多対1では外部キーを持つ側、多対多では @JoinTable を付けた側を「所有側(owner)」と呼びます。多対多の外部キーは、エンティティのテーブルではなく中間テーブルに作られます。

関係 所有側に付けるもの 反対側
多対1・1対多 @ManyToOne(外部キーを自動で作成) @OneToMany
1対1 @OneToOne + @JoinColumn @OneToOne
多対多 @ManyToMany + @JoinTable @ManyToMany

ManyToOneとOneToManyの対応

先ほどの Post.author(@ManyToOne)と User.posts(@OneToMany)は、第2引数で互いのプロパティを指し合っています。外部キー列 authorId は所有側の post テーブルに作られます。公式ドキュメントのとおり、@OneToMany は反対側の @ManyToOne がなければ使えません。逆に @ManyToOne だけを定義することはできます。relations: { posts: true } でユーザーを取得すると、次のように LEFT JOIN で投稿が読み込まれました(列リストは省略)。

SELECT ... FROM "user" "User" LEFT JOIN "post" "User__User_posts" ON "User__User_posts"."authorId"="User"."id" WHERE (("User"."nickname" IS NULL))

nullable: falseでINNER JOINになる挙動

1.0からは、nullable: false を付けた @ManyToOne と、所有側の @OneToOne を relations で読み込むと INNER JOIN が使われます。検証でも、Post を relations: { author: true } で取得したSQLは INNER JOIN でした。外部キーがNOT NULLで、参照先の行が必ず存在するなら結果は変わりません。ただし、実際のテーブルでは外部キーがNULL許可のままになっている場合や、参照先の無い行が残っている場合は、その行が結果から消えます。移行時は、エンティティの nullable とDBの実際の定義が一致しているかを確認してください。関連先に @DeleteDateColumn がある場合は例外で、LEFT JOIN のままです。

OneToOneとManyToManyの所有側

1対1では、@JoinColumn() を外部キーを持つ側だけに付けます。公式ドキュメントはこれを必須とし、両側に付けてはいけないと明記しています。多対多では @JoinTable() が必須で、これも片側だけに付けます。付けた側のエンティティ名を元に、中間テーブル(例:question_categories_category)が作られます。中間テーブルに作成日時などの列を持たせたい場合は、@ManyToMany ではなく中間エンティティを定義し、@ManyToOne を2本張る設計にします。

EagerとLazyの使い分け

eager: true を付けたリレーションは、find系メソッドで自動的に読み込まれます。ただし公式ドキュメントのとおり、QueryBuilderでは無効で、leftJoinAndSelect を書く必要があります。また、eagerはリレーションの片側にしか付けられません。Lazyリレーションは、プロパティの型を Promise<Post[]> にし、await したときに別クエリで読み込む方式です。一覧画面でLazyを使うと、行ごとにクエリが発行されるN+1問題が起きやすくなります。一覧では relations かJOINで一度に取得し、eagerとLazyは使う場所を限定するのが安全です。

マイグレーションによるスキーマ管理

synchronizeを本番で使わない理由

synchronize: true は、起動のたびにエンティティとDBの差分を自動で反映します。公式のDataSourceオプションの説明には「本番では使わないこと。本番データを失う恐れがある」とあります。検証でも、SQLiteで外部キーを追加する際、TypeORMは temporary_post テーブルを作り、データを移してから元のテーブルを DROP していました。どのような変更SQLが流れるかを事前に確認できないまま本番のテーブルが作り直されるため、開発初期だけ有効にし、共有する環境ではマイグレーションに切り替えます。

generate・run・revertのコマンド

TypeORMのCLIは typeorm コマンドで、-d にDataSourceのファイルを渡します。検証では、コンパイル済みのJavaScriptに対してCLIを実行しました。この方法ならts-nodeを入れる必要がありません。

npx tsc
npx typeorm migration:generate src/migrations/Init -d dist/data-source.js
npx tsc
npx typeorm migration:run -d dist/data-source.js
npx typeorm migration:show -d dist/data-source.js

# 取り消す場合だけ実行する(テーブルが消えるので、続けて使うなら再度runする)
npx typeorm migration:revert -d dist/data-source.js
npx typeorm migration:run -d dist/data-source.js

migration:generate は、エンティティと現在のDBを比べて差分のSQLを up、元に戻すSQLを down に書いたファイルを作ります(今回は src/migrations/1789637666312-Init.ts)。差分が無いときは No changes in database schema were found - cannot generate a migration. と表示され、ファイルは作られません。空のマイグレーションを手で書く場合は migration:create を使います。migration:show は適用済みを [X] で表示します。migration:revert は最後に適用した1件の down を実行します。

生成されたSQLは、コミット前に必ず読んでください。検証で nickname を displayName に改名したところ、SQLiteでは temporary_user を作って INSERT INTO ... SELECT で旧列の値を移し、元の user テーブルを DROP するSQLが生成されました。データは引き継がれますが、行数の多いテーブルでは作り直しに時間がかかり、その間は書き込みができません。本番環境では、アプリの起動時に runMigrations() を自動実行するより、デプロイの手順でCLIを1回だけ実行するほうが安全です。複数台が同時に起動しても、マイグレーションが二重に走りません。

データ取得のfind APIとQueryBuilder

ここからのコード片は、検証用の src/main.ts の main() 関数の中で実行したものです。関数の冒頭では、DataSourceを初期化してマイグレーションを適用し、[email protected] のユーザーと投稿2件をトランザクションで保存しています。関数の末尾では AppDataSource.destroy() で接続を閉じています。

import { IsNull } from "typeorm"
import { AppDataSource } from "./data-source"
import { User } from "./entities/User"
import { Post } from "./entities/Post"

async function main() {
    await AppDataSource.initialize()
    await AppDataSource.runMigrations()

    await AppDataSource.transaction(async (manager) => {
        const user = await manager.save(User, { email: "[email protected]", nickname: null })
        await manager.save(Post, [
            { title: "TypeORM 1.1を試す", author: user },
            { title: "下書き", author: user },
        ])
    })

npx tsc でコンパイルし、node dist/main.js で実行しました。単純な条件の検索は、リポジトリの find 系メソッドで書きます。1.x系では、select、relations、order をオブジェクト形式で指定します。

const users = await AppDataSource.getRepository(User).find({
    where: { nickname: IsNull() },
    relations: { posts: true },
})

集計や複雑なJOIN、取得する列の絞り込みはQueryBuilderで書きます。値は :published のような名前付きパラメータで渡し、文字列連結でSQLに埋め込まないようにします。

const rows = await AppDataSource.getRepository(Post)
    .createQueryBuilder("post")
    .innerJoin("post.author", "author")
    .select(["post.title AS title", "author.email AS email"])
    .where("post.published = :published", { published: false })
    .orderBy("post.id", "ASC")
    .getRawMany()

発行されたSQLと、返ってきた結果は次のとおりです。

SELECT "post"."title" AS title, "author"."email" AS email FROM "post" "post" INNER JOIN "user" "author" ON "author"."id"="post"."authorId" WHERE "post"."published" = ? ORDER BY "post"."id" ASC -- PARAMETERS: [0]
[
  { title: 'TypeORM 1.1を試す', email: '[email protected]' },
  { title: '下書き', email: '[email protected]' }
]

getRawMany() は、エンティティではなく列名をキーにしたオブジェクトを返します。エンティティとして受け取りたい場合は、innerJoinAndSelect と getMany() を組み合わせ、独自の別名を付けた select() は外します。別名付きの select() を残したまま getMany() を呼ぶと、検証では0件の配列が返りました。select() を外すと、author を含む Post のインスタンスが返りました。1.0では、orderBy に渡した値の検証と、スキーマ操作での識別子のエスケープが全ドライバに入りました。いずれもSQLインジェクション対策としてリリースノートに記載されています。

トランザクションの書き方

dataSource.transaction() に渡したコールバックの中では、引数の manager を通して操作します。コールバックが例外を投げると、それまでの変更はすべてロールバックされます。検証では、メールアドレスが重複するユーザーを2件目に保存させて、ロールバックを確認しました。

try {
    await AppDataSource.transaction(async (manager) => {
        await manager.save(User, { email: "[email protected]" })
        await manager.save(User, { email: "[email protected]" })
    })
} catch (e) {
    console.log("rollback:", await AppDataSource.getRepository(User).count())
}

このコードを実行すると、UNIQUE constraint failed: user.email で2件目の INSERT が失敗し、ROLLBACK が発行されました。1件目の [email protected] も残らず、ユーザー数は1件のままでした。コールバック内で AppDataSource.getRepository() を直接使うと、その操作がトランザクションに参加することは保証されません。公式ドキュメントの指示どおり、必ず manager を使ってください。

接続の取得や解放を自分で制御したい場合は、dataSource.createQueryRunner() で startTransaction()・commitTransaction()・rollbackTransaction() を呼び、finally で release() します。1.0からは await using 構文(TypeScript 5.2以降)で、QueryRunnerを自動で解放できます。分離レベルは、DataSourceの isolationLevel で全ドライバの既定値を設定できるようになりました。

よくあるエラーと対処

  • No metadata for "X" was found:エンティティが entities に登録されていない、またはglobの拡張子が実行環境(.tsか.jsか)と合っていません。
  • Undefined value encountered in property …:1.x系で、where条件にundefinedが入っています。その項目で絞り込まないなら条件オブジェクトから除き、NULLの行だけを探したいなら IsNull() を使います。
  • Empty criteria(s) are not allowed for the update method.:1.1.0以降で、update() や delete() の条件が空になっています。
  • createConnectionやgetConnectionが見つからない:1.x系で削除されたAPIを呼んでいます。new DataSource() と initialize() に書き換えます。
  • sqlite3ドライバが読み込まれない:1.x系では、type: "better-sqlite3" とbetter-sqlite3パッケージに切り替えます。オプションの busyTimeout は timeout に名前が変わりました。
  • No changes in database schema were found:migration:generate で差分が無い状態です。エンティティの変更がビルド後のJSに反映されているか確認します。

NestJSの起動時に、Connection に関連するエラーで落ちる場合は、@nestjs/typeorm が11.0.1より古い版のままになっています。

TypeORMを選ぶ条件と避けるべき場面

TypeORMが向いているのは、クラスとデコレーターでモデルを書く設計(NestJSなど)を採用している場合、SQLに近い書き方でJOINや集計を組みたい場合、PostgreSQLとOracleのように複数のDBを同じ書き方で扱いたい場合です。1.0が出たことで、長く言われていた「開発が止まっている」という懸念は当てはまらなくなりました。開発者向け文書によると、nightly版は毎日UTC 2時に、前回の公開以降にコミットがあれば自動で公開されます。2026年9月6日から17日までは、毎日公開されていました。

避けるべきなのは、型安全を最優先する場合です。getRawMany() の戻り値や、QueryBuilderに文字列で書いた列名は、コンパイル時に検査されません。スキーマファイルから型を生成するPrismaや、SQLに近い書き方で結果の型まで推論するDrizzleのほうが、列名の打ち間違いをコンパイル時に見つけられます。PrismaとTypeORMの比較はTypeORMとPrismaの比較記事で、Drizzleの特徴はDrizzle ORMの解説で詳しく扱っています。

よくある質問

TypeORMとは何ですか?

TypeScriptのクラスとデコレーターでテーブルを定義し、リポジトリやQueryBuilderでDBを操作するNode.js向けのORMです。PostgreSQL、MySQL、SQLite、SQL Server、Oracle、MongoDBなどに対応しています。

TypeORMの最新バージョンはいくつですか?

2026年9月17日時点で、npmのlatestは1.1.1(2026年9月1日公開)です。0.3系は legacy タグで0.3.31が公開されています。最新の版は npm view typeorm dist-tags で確認できます。

0.3系のコードは1.x系でそのまま動きますか?

非推奨APIを使っていなければ、多くはそのまま動きます。ただし、where条件のnull・undefinedが例外になる変更と、nullable: false のリレーションがINNER JOINになる変更は、コンパイルでは検出できず実行時に表面化します。npx @typeorm/codemod v1 src/ で書き換えたうえで、テストを実行してください。

NestJSでTypeORM 1.xを使うには何が必要ですか?

@nestjs/typeorm をv11.0.1以降に上げます。v10とv11.0.0は起動時に落ちます。環境変数から接続情報を読む設定は、ConfigModuleでNestJSの環境変数を型安全に管理する方法を参考にしてください。

synchronize: trueは使ってもよいですか?

開発初期のローカル環境に限れば使えます。公式ドキュメントは本番での使用を禁じています。共有DBと本番では、migration:generate で差分を確認してから migration:run で適用します。

関連記事

お気に入りに入れた記事の一覧

資料請求

RELATED POSTS 関連記事

目次