首页 / 资讯中心 / 文章详情

SeaORM 迁移 CLI 完全指南:基于 actix_example 的 cargo run 子命令实战与源码解析

SeaORM 迁移 CLI 完全指南:基于 actix_example 的 cargo run 子命令实战与源码解析 ★ FEATURED ARTICLE
后端数据库ORM【免费下载链接】sea-orm A powerful relational ORM for Rust项目地址https://gitcode.com/gh_mirrors/se/sea-orm点击查看免费下载本指南以 SeaORM 仓库中 actix_example 迁移模块的官方说明examples/actix_example/migration/README.md为骨架系统讲解通过cargo run驱动sea-orm-migration的八个核心子命令up、down、fresh、refresh、reset、status等并结合仓库源码剖析每个命令在MigratorTrait层的真实执行逻辑。读完本文你将掌握 SeaORM 数据库迁移的标准操作流程、每个命令的适用场景与副作用边界以及如何基于迁移文件编写建表与数据播种代码。迁移模块在项目中的位置在 actix_example 示例中数据库迁移被组织为独立的migrationcrate与api应用服务、entity实体定义并列构成标准的 SeaORM 三层结构examples/actix_example/migration/迁移定义与 CLI 入口examples/actix_example/entity/表对应的 Entity 模型examples/actix_example/api/基于 Actix 4 的业务服务迁移 crate 的依赖配置见 examples/actix_example/migration/Cargo.toml其中关键点在于sea-orm-migration依赖必须显式启用运行时与数据库后端特性[dependencies.sea-orm-migration] features [ # Enable following runtime and db backend features if you want to run migration via CLI runtime-tokio-native-tls, sqlx-mysql, ] path ../../../sea-orm-migration # remove this line in your own project version ~2.0.3 # sea-orm-migration version注意示例中以本地路径引用sea-orm-migration源码方便仓库内联调试在你的独立项目中应删除path行仅保留version。特性按需选择——使用 MySQL 启用sqlx-mysqlPostgreSQL 对应sqlx-postgresSQLite 对应sqlx-sqlite运行时则在runtime-tokio-native-tls或runtime-tokio-rustls等选项中二选一。CLI 入口非常精简见 examples/actix_example/migration/src/main.rsuse sea_orm_migration::prelude::*; #[tokio::main] async fn main() { cli::run_cli(migration::Migrator).await; }而 examples/actix_example/migration/src/lib.rs 则把每个迁移文件注册进Migratorpub use sea_orm_migration::prelude::*; mod m20220120_000001_create_post_table; mod m20220120_000002_seed_posts; pub struct Migrator; #[async_trait::async_trait] impl MigratorTrait for Migrator { fn migrations() - VecBoxdyn MigrationTrait { vec![ Box::new(m20220120_000001_create_post_table::Migration), Box::new(m20220120_000002_seed_posts::Migration), ] } }Migrator实现了MigratorTrait其migrations()返回按注册顺序排列的迁移列表——这正是cargo run各子命令遍历和执行的依据。整个迁移模块在 workspace 中可以通过cargo run -p migration直接运行见 examples/actix_example/README.md 中的示例cargo run -p migration -- up。运行前置条件DATABASE_URL 与连接建立所有迁移命令在执行前都必须先建立数据库连接。cli::run_cli的内部实现sea-orm-migration/src/cli.rs会按以下顺序解析连接信息调用dotenv().ok()加载项目根目录.env文件通过 clap 解析命令行参数其中-u/--database-url为全局参数同时支持DATABASE_URL环境变量env DATABASE_URL若未提供连接串直接报错Environment variable DATABASE_URL not set使用ConnectOptions::new(url)创建连接若提供-s/--database-schema或DATABASE_SCHEMA环境变量则调用set_schema_search_path(schema)默认值为public。在 actix_example 中应用与迁移共享同一个.env文件启动前的标准准备步骤是修改.env中的DATABASE_URL指向目标数据库如mysql://root:rootlocalhost:3306/actix_example并在migration/Cargo.toml中开启对应的数据库后端特性。此外-v--verbose是全局调试开关。从 cli.rs 的setup_tracing可以看到非 verbose 模式只输出sea_orm_migrationinfo级别的精简日志不带时间、目标和级别前缀verbose 模式则输出debug级别的完整日志适合排查迁移失败原因。八个核心子命令详解官方文档 examples/actix_example/migration/README.md 完整列出了 Migrator CLI 的全部命令。以下逐条展开并结合MigrateSubcommands枚举sea-orm-cli/src/cli.rs与MigratorTrait实现sea-orm-migration/src/migrator.rs说明其底层行为。应用全部待执行迁移cargo run不携带任何子命令时等同于up执行所有尚未应用的迁移。命令分发逻辑见 cli.rs 中的run_migrate_inner其_ migrator.up(db, None).await?分支即默认兜底路径steps None表示“应用全部”。这也是首次部署数据库时最常用的命令。cargo run -- up显式调用up语义与默认行为完全一致。首次执行时SeaORM 会在数据库中创建名为seaql_migrations的迁移记录表MigratorTrait::install见 migrator.rs随后逐条执行migrations()中注册的迁移并记录版本。仅应用前 N 个待执行迁移cargo run -- up -n 10-n--num参数为Optionu32用于限制本次应用的迁移数量。底层调用migrator.up(db, Some(10))。当迁移链较长、希望分批观察效果时例如先应用 10 个再逐步推进该参数非常实用也可在 CI 中作为“分阶段发布”的控制手段。回滚最近应用的迁移cargo run -- down回滚最近一次应用的迁移。MigrateSubcommands::Down的num参数默认值为1见 sea-orm-cli/src/cli.rs因此不带-n时只回滚最新一个迁移执行对应迁移的down方法并删除迁移记录。cargo run -- down -n 10一次回滚最近 10 个迁移。注意与up -n的区别down -n的num是必填默认参数默认1语义为“回滚 N 个”而up -n的num为可空参数为空表示全部。回滚顺序与执行顺序严格相反后执行的先回滚这与down方法的设计假设一致。清空数据库后重新应用全部迁移cargo run -- freshfresh的执行链路migrator.rs 中的exec_fresh为先install迁移记录表再调用drop_everything删除数据库中的全部表最后从头应用所有迁移。它最适合开发/测试环境的“一键重建”把库打回原形再完整重建验证迁移脚本在空库上的可执行性。请勿在生产数据库上使用——drop_everything会摧毁所有数据。先全部回滚再重新应用cargo run -- refreshrefresh与fresh的最大区别在于不清空数据库它先执行exec_down(manager, None)逐个回滚所有已应用迁移依次触发每个迁移的down再执行exec_up(manager, None)重新全部应用。相比fresh它保留表中未被迁移管理的数据适合验证down/up成对往返的一致性若迁移脚本的down实现不完整此命令会失败。回滚全部迁移cargo run -- resetreset执行完整的回滚exec_down(manager, None)回滚所有迁移后再调用uninstall删除seaql_migrations迁移记录表。结果是一个“从未执行过迁移”的数据库——表结构恢复原状迁移历史清零。下次执行up时 SeaORM 会重新创建seaql_migrations并从第一个迁移开始。查看迁移状态cargo run -- statusstatus不会修改数据库只做检查先确保seaql_migrations存在必要时创建再通过get_migration_with_status逐一输出每个迁移的状态info!(Migration {}... {}, migration.name(), status)。它可用于确认哪些迁移已应用、哪些待应用是排查“迁移对不上”问题的第一工具。从源码看命令分发与执行模型在 sea-orm-migration/src/cli.rs 中run_migrate_inner对子命令做了明确映射这也是一份现成的“命令 → 底层方法”对照表match command { Some(MigrateSubcommands::Fresh) migrator.fresh(db).await?, Some(MigrateSubcommands::Refresh) migrator.refresh(db).await?, Some(MigrateSubcommands::Reset) migrator.reset(db).await?, Some(MigrateSubcommands::Status) migrator.status(db).await?, Some(MigrateSubcommands::Up { num }) migrator.up(db, num).await?, Some(MigrateSubcommands::Down { num }) migrator.down(db, Some(num)).await?, _ migrator.up(db, None).await?, }对应的MigratorTrait方法语义migrator.rsCLI 命令MigratorTrait 方法数据库影响是否触发 down默认/ upup(db, steps)应用待执行迁移否up -n Nup(db, Some(N))应用前 N 个迁移否downdown(db, Some(1))回滚最近 1 个是down -n Ndown(db, Some(N))回滚最近 N 个是freshfresh(db)先drop_everything清空所有表再全量应用否但清空数据refreshrefresh(db)先全量回滚再全量应用是resetreset(db)先全量回滚再删除seaql_migrations是statusstatus(db)只读检查无结构变更否值得强调的是MigratorTrait的这些方法都是async fn配合#[tokio::main]入口main.rs迁移全程运行在 Tokio 异步运行时之上因此sea-orm-migration依赖中的runtime-tokio-*特性是 CLI 可运行的必要前提。迁移文件长什么样建表与数据播种官方文档给出的命令集之所以能对示例生效是因为仓库提供了两个真实的迁移实现可作为编写迁移的最佳范式。迁移一创建 post 表见 examples/actix_example/migration/src/m20220120_000001_create_post_table.rsuse sea_orm_migration::{prelude::*, schema::*}; #[derive(DeriveMigrationName)] pub struct Migration; #[async_trait::async_trait] impl MigrationTrait for Migration { async fn up(self, manager: SchemaManager) - Result(), DbErr { manager .create_table( Table::create() .table(post) .if_not_exists() .col(pk_auto(id)) .col(string(title)) .col(string(text)) .to_owned(), ) .await } async fn down(self, manager: SchemaManager) - Result(), DbErr { manager .drop_table(Table::drop().table(post).to_owned()) .await } }要点解析#[derive(DeriveMigrationName)]自动以文件名m20220120_000001_create_post_table作为迁移的唯一标识用于seaql_migrations记录schema::*提供了pk_auto自增主键、string变长字符串等便捷构造器up与down成对实现——up建表down删表这是refresh/reset能安全往返的前提表结构与 entity/src/post.rs 中的Modelid: i32、title: String、text: String保持一致保证 ORM 读写与迁移脚本不脱节。迁移二播种示例数据见 examples/actix_example/migration/src/m20220120_000002_seed_posts.rs。迁移不只限于 DDL也可以在up中通过manager.get_connection()获取连接用 ActiveModel 写入初始化数据use entity::post; use sea_orm::{ActiveModelTrait, ColumnTrait, EntityTrait, QueryFilter, Set}; use sea_orm_migration::prelude::*; #[derive(DeriveMigrationName)] pub struct Migration; #[async_trait::async_trait] impl MigrationTrait for Migration { async fn up(self, manager: SchemaManager) - Result(), DbErr { let db manager.get_connection(); let seed_data vec![ (First Post, This is the first post.), (Second Post, This is another post.), ]; for (title, text) in seed_data { let model post::ActiveModel { title: Set(title.to_string()), text: Set(text.to_string()), ..Default::default() }; model.insert(db).await?; } println!(Posts table seeded successfully.); Ok(()) } async fn down(self, manager: SchemaManager) - Result(), DbErr { let db manager.get_connection(); let titles_to_delete vec![First Post, Second Post]; post::Entity::delete_many() .filter(post::Column::Title.is_in(titles_to_delete)) .exec(db) .await?; println!(Posts seeded data removed.); Ok(()) } }这展示了两个进阶实践种子数据随迁移管理up播种、down清理保证refresh时不会产生重复数据——删除操作按标题精确过滤is_in与播种数据一一对应迁移与实体层协作迁移 crate 依赖entitycrate直接在迁移中复用post::ActiveModel与post::Entity避免了重复手写 SQL。典型工作流从零到可部署综合官方文档与示例的工程实践一次完整的迁移生命周期通常如下配置连接在项目根目录创建.env写入DATABASE_URL...actix_example 的完整启动流程见 examples/actix_example/README.md编写迁移新建mYYYYMMDD_HHMMSS_xxx.rs实现up/down并注册进Migrator::migrations()本地验证先cargo run -- status确认基线再cargo run -- up应用反复调整时可使用down -n 1回滚单步、refresh重放重建环境开发机或 CI 环境需要干净库时用fresh需要保留数据但验证迁移往返时用refresh上线前检查status确认无遗留未应用迁移再对生产库执行upfresh/reset严禁用于生产。常见问题与注意事项DATABASE_URL未设置cli.rs会在缺失环境变量时直接报错退出请确认.env存在且格式为DATABASE_URL...且当前工作目录位于项目根dotenv()默认从当前目录加载。特性未开启sea-orm-migration未启用对应数据库后端特性时编译期即报错按 Cargo.toml 中的注释所示开启sqlx-*与runtime-tokio-*特性。PostgreSQL schema默认搜索路径为public如需切换 schema 使用cargo run -- -s my_schema up或设置DATABASE_SCHEMA环境变量MySQL 与 SQLite 会忽略该参数见 cli.rs 中参数说明。fresh与reset的数据风险fresh会drop_everything清空所有表reset会回滚所有迁移并删除迁移记录表两者均不可逆务必在副本或开发库上使用。迁移命名与顺序DeriveMigrationName以文件名为准命名中的时间戳前缀如m20220120_000001决定了迁移的先后语义新建迁移时保持时间戳递增可避免顺序混乱。通过以上命令集与源码级认知你已经可以像操作 actix_example 一样在任何 SeaORM 项目中安全、高效地管理数据库结构的演进。赞分享后端数据库ORM【免费下载链接】sea-orm A powerful relational ORM for Rust项目地址https://gitcode.com/gh_mirrors/se/sea-orm点击查看免费下载相关推荐SeaORM 迁移 CLI 完全指南掌握 cargo run 全套命令与 Migrator 实战SeaORM 迁移 CLI 完全指南掌握 cargo run 全套命令与 Migrator 实战 本篇技术指南聚焦 SeaORM当前仓库 gh_mirror后端数据库ORMSeaORM Migration CLI 实战指南基于 loco_starter 的数据库迁移命令全解析SeaORM Migration CLI 实战指南基于 loco_starter 的数据库迁移命令全解析 本指南以 examples/loco_starter后端数据库ORMSeaORM Migrator CLI 迁移命令实战指南基于 salvo_example 的数据库迁移管理SeaORM Migrator CLI 迁移命令实战指南基于 salvo_example 的数据库迁移管理 本篇技术指南以 SeaORM 官方示例项目 sal后端数据库ORM上一篇Seer项目教程探索数据的奥秘下一篇LatencyFleX: 低延迟游戏体验增强工具创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
阅读完成 · 觉得有帮助?
咨询建站