Skip to main content
Version: 6.4

模式生成器

SchemaGenerator 可能会损害你的数据库。它将删除或更改表、索引、序列等。请在开发中谨慎使用此工具,而不是在生产服务器上使用。它旨在帮助你开发数据库模式,但不是在生产中将模式从 A 迁移到 B。一种安全的方法是生成开发服务器上的 SQL 并将其保存到在生产服务器上手动执行的 SQL 迁移文件中。

¥SchemaGenerator can do harm to your database. It will drop or alter tables, indexes, sequences and such. Please use this tool with caution in development and not on a production server. It is meant for helping you develop your Database Schema, but NOT with migrating schema from A to B in production. A safe approach would be generating the SQL on development server and saving it into SQL Migration files that are executed manually on the production server.

SchemaGenerator 假定你的项目自己使用给定的数据库。如果更新和删除命令与使用 MikroORM 的当前项目无关,它们将与其他表混淆。请小心!

¥SchemaGenerator assumes your project uses the given database on its own. Update and Drop commands will mess with other tables if they are not related to the current project that is using MikroORM. Please be careful!

要从实体元数据生成模式,你可以使用 SchemaGenerator 助手。

¥To generate schema from your entity metadata, you can use SchemaGenerator helper.

你可以通过 CLI 使用它:

¥You can use it via CLI:

要使用 CLI,请先在本地安装 @mikro-orm/cli 包。版本需要与 @mikro-orm/core 包保持一致。

¥To work with the CLI, first install @mikro-orm/cli package locally. The version needs to be aligned with the @mikro-orm/core package.

npx mikro-orm schema:create --dump   # Dumps create schema SQL
npx mikro-orm schema:update --dump # Dumps update schema SQL
npx mikro-orm schema:drop --dump # Dumps drop schema SQL

你还可以使用 --run 标志来触发所有查询,但要小心,因为它可能会破坏你的数据库。在执行之前,请务必先检查生成的 SQL。不要在生产中使用 --run 标志!

¥You can also use --run flag to fire all queries, but be careful as it might break your database. Be sure to always check the generated SQL first before executing. Do not use --run flag in production!

如果数据库不存在,schema:create 将自动创建数据库。

¥schema:create will automatically create the database if it does not exist.

schema:update 默认删除所有未知表,你可以使用 --no-drop-tables 来绕过它。还有 --safe 标志,它将禁用表删除和列删除。

¥schema:update drops all unknown tables by default, you can use --no-drop-tables to get around it. There is also --safe flag that will disable both table dropping and column dropping.

schema:drop 默认会删除所有数据库表。你可以使用 --drop-db 标志来删除整个数据库。

¥schema:drop will by default drop all database tables. You can use --drop-db flag to drop the whole database instead.

npx mikro-orm schema:fresh --run     # !WARNING! Drops the database schema and recreates it

此命令可以与 --seed 选项一起运行,以便在再次创建数据库后为其播种。

¥This command can be run with the --seed option to seed the database after it has been created again.

npx mikro-orm schema:fresh --run --seed              # seed the database with the default database seeder
npx mikro-orm schema:fresh --run --seed=UsersSeeder # seed the database with the UsersSeeder

你可以在 orm 配置中使用键 config.seeder.defaultSeeder 指定默认数据库种子

¥You can specify the default database seeder in the orm config with the key config.seeder.defaultSeeder

配置

¥Configuration

我们可以通过 ORM 配置全局配置模式生成器:

¥We can configure the schema generator globally via the ORM config:

const orm = await MikroORM.init({
// default values:
schemaGenerator: {
disableForeignKeys: true, // wrap statements with `set foreign_key_checks = 0` or equivalent
createForeignKeyConstraints: true, // whether to generate FK constraints
ignoreSchema: [], // allows ignoring some schemas when diffing
},
});

请注意,如果我们禁用 FK 约束并且当前架构正在使用它们,则架构差异将尝试删除已经存在的约束。

¥Note that if we disable FK constraints and current schema is using them, the schema diffing will try to remove those that already exist.

以编程方式使用 SchemaGenerator

¥Using SchemaGenerator programmatically

或者你可以创建一个简单的脚本,像这样初始化 MikroORM:

¥Or you can create simple script where you initialize MikroORM like this:

./create-schema.ts
import { MikroORM } from '@mikro-orm/core';

(async () => {
const orm = await MikroORM.init({
entities: [Author, Book, ...],
dbName: 'your-db-name',
// ...
});
const generator = orm.schema;

const dropDump = await generator.getDropSchemaSQL();
console.log(dropDump);

const createDump = await generator.getCreateSchemaSQL();
console.log(createDump);

const updateDump = await generator.getUpdateSchemaSQL();
console.log(updateDump);

// there is also `generate()` method that returns drop + create queries
const dropAndCreateDump = await generator.generate();
console.log(dropAndCreateDump);

// or you can run those queries directly, but be sure to check them first!
await generator.dropSchema();
await generator.createSchema();
await generator.updateSchema();

// in tests it can be handy to use those:
await generator.refreshDatabase(); // ensure db exists and is fresh
await generator.clearDatabase(); // removes all data

await orm.close(true);
})();

然后通过 ts-node 运行此脚本(或将其编译为纯 JS 并使用 node):

¥Then run this script via ts-node (or compile it to plain JS and use node):

$ ts-node create-schema

忽略特定列更改

¥Ignoring specific column changes

使用生成的列时,除非我们将 ignoreSchemaChanges 设置为忽略对 typeextra 的更改,否则每次运行 SchemaGenerator 时我们都会得到永久差异。

¥When using generated columns, we'll get a perpetual diff on every SchemaGenerator run unless we set ignoreSchemaChanges to ignore changes to type and extra.

有关更多信息,请参阅 SQL 生成的列

¥See the SQL Generated columns section for more details.

SQLite 的限制

¥Limitations of SQLite

SQLite 数据库存在局限性,因此其行为与其他 SQL 驱动程序不同。也就是说,不可能:

¥There are limitations of SQLite database because of which it behaves differently than other SQL drivers. Namely, it is not possible to:

  • 更改列时创建外键约束

    ¥create foreign key constraints when altering columns

  • 创建没有列的空表

    ¥create empty tables without columns

  • 更改列需要可空性

    ¥alter column requires nullability

因此,你最终可能会使用 SQLite 获得不同的模式,因此不建议使用 SQLite 进行应用的集成测试。

¥Because of this, you can end up with different schema with SQLite, so it is not suggested to use SQLite for integration tests of your application.

调试

¥Debugging

有时模式差异可能无法按预期工作并会产生不必要的查询。这通常是你设置属性的 columnTypedefault/defaultRaw 选项的方式存在的问题。你可以使用 MIKRO_ORM_CLI_VERBOSE 环境变量来启用 CLI 的详细日志记录,这反过来又启用了用于提取当前模式的底层查询和 SchemaComparator 中的日志,这应该有助于你理解为什么 ORM 将两列视为不同的(以及哪些特定选项不同)。

¥Sometimes the schema diffing might not work as expected and will produce unwanted queries. Often this is a problem with how you set up the columnType or default/defaultRaw options of your properties. You can use MIKRO_ORM_CLI_VERBOSE env var to enable verbose logging of the CLI, which in turn enables both the underlying queries used to extract the current schema, and logs in the SchemaComparator which should help you understand why the ORM sees two columns as different (and what particular options are different).

$ MIKRO_ORM_CLI_VERBOSE=1 npx mikro-orm schema:update --dump