数据库迁移
Finch 内置迁移系统,用于管理随时间推移的模式变更。
迁移命令
| 命令 | 描述 |
|---|---|
finch migrate --init |
运行所有待执行的迁移 |
finch migrate --create --name <name> |
创建新的迁移文件 |
finch migrate --rollback |
回滚最后一次迁移 |
finch migrate --list |
显示所有迁移的状态 |
finch migrate --init --sqlite |
为 SQLite 运行 |
finch migrate --create --name <name> --sqlite |
为 SQLite 创建 |
迁移文件结构
迁移文件位于 ./migrations/(MySQL)或 ./migrations_sqlite/(SQLite):
-- NEW VERSION
CREATE TABLE articles (
id INT PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(255) NOT NULL,
body TEXT,
published TINYINT(1) DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- ROLL BACK
DROP TABLE IF EXISTS articles;
每个迁移文件必须包含 -- NEW VERSION 部分(用于应用)和 -- ROLL BACK 部分(用于回滚)。
每个迁移(基于文件或基于 Dart)都在数据库事务中执行:如果任何语句失败,事务将自动回滚,该迁移也不会被标记为已应用。
基于 Dart 的迁移
除了 SQL 文件,你还可以通过继承 DartMigration 用 Dart 定义迁移。使用 addSql() 构建 up()/down() 的 SQL,并设置 target 来选择 MigrationTarget.mysql 或 MigrationTarget.sqlite:
import 'package:finch/mysql.dart';
class M1CreateUsers extends DartMigration {
@override
MigrationTarget get target => MigrationTarget.sqlite;
M1CreateUsers() : super('m1_create_users');
@override
void up() {
addSql('''
CREATE TABLE users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT,
email TEXT
);
''');
}
@override
void down() {
addSql('DROP TABLE IF EXISTS users;');
}
}
在 FinchApp 实例上注册迁移。传给 super(...) 的名称在所有已注册的迁移中必须是唯一的:
final app = FinchApp(configs: configs)
..registerDartMigration([
M1CreateUsers(),
M2InsertUsers(),
]);
注册后,migrate --init、--rollback 和 --list(及其 --sqlite / migrate_sqlite 对应命令)会运行匹配该 target 的 Dart 迁移,而不是读取迁移文件。
文件命名
迁移文件以时间戳命名:
2024_01_15_143022_create_articles_table.sql
启动时自动运行
你可以在应用启动时自动运行迁移:
FinchConfigs(
autoMigrate: true,
)
警告:在生产环境中谨慎使用此选项。
示例工作流
# 为新表创建迁移
finch migrate --create --name create_products_table
# 编辑 migrations/ 中生成的文件
# 然后运行迁移
finch migrate --init
# 如需回滚
finch migrate --rollback