尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

SeaORM 与 Seaography 实战:用 Rust 从数据库一键生成 GraphQL API

发布时间:2026/9/24 16:11:02

资讯中心
01
ARTICLE

SeaORM 与 Seaography 实战:用 Rust 从数据库一键生成 GraphQL API

SeaORM 与 Seaography 实战:用 Rust 从数据库一键生成 GraphQL API
后端数据库ORM【免费下载链接】sea-orm A powerful relational ORM for Rust项目地址https://gitcode.com/gh_mirrors/se/sea-orm点击查看免费下载导读本文基于 SeaORM 仓库中的 seaography_example 完整示例系统讲解如何将 SeaORM 实体模型与 Seaography 结合从现有数据库Bakery 面包店 Schema一键生成可运行的 GraphQL API 服务。你将掌握如何初始化数据库并运行迁移、如何安装sea-orm-cli与seaography-cli两条 CLI 工具链、如何用代码生成器产出 GraphQL 工程以及如何在 GraphQL Playground 中编写筛选、聚合与多级关联查询。读完本文你可以在自己的 Rust 项目中复刻数据库 → 实体 → GraphQL 服务的完整流水线。示例概览Bakery 面包店 Schema整个示例围绕一个面包店业务模型展开涉及 6 张业务表与 1 张多对多关联表仓库中已经包含了迁移定义、种子数据与已生成的 SQLite 数据库文件bakery.db。核心实体及其关系如下bakery面包店id、name、profit_margin拥有多个bakers与多个cakesbaker面包师id、name、contact、bakery_id可空通过cake_baker与cakes多对多关联cake蛋糕id、name、priceDecimal、bakery_id、gluten_free通过cake_baker与bakers多对多关联cake_baker关联表cake_idbaker_id复合主键用于表达蛋糕由哪些面包师制作customer、order、lineitem顾客、订单与订单行明细构成完整的零售业务链路。从生成的实体代码可以看到 SeaORM 的关系定义方式cake.rs#[sea_orm::model] #[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)] #[sea_orm(table_name cake)] pub struct Model { #[sea_orm(primary_key)] pub id: i32, pub name: String, #[sea_orm(column_type Decimal(Some((16, 4))))] pub price: Decimal, pub bakery_id: i32, pub gluten_free: bool, #[sea_orm( belongs_to, from bakery_id, to id, on_update Cascade, on_delete Cascade )] pub bakery: BelongsTosuper::bakery::Entity, #[sea_orm(has_many, via cake_baker)] pub bakers: HasManysuper::baker::Entity, } impl ActiveModelBehavior for ActiveModel {}正是这些belongs_to/has_many/has_many(via ...)声明让 Seaography 在构建 GraphQL Schema 时能够自动推导出可嵌套查询的对象关系。运行示例项目1. 指定数据库连接示例默认使用 SQLite 数据库通过环境变量DATABASE_URL指定连接地址。仓库已自带bakery.db直接用只读模式连接即可export DATABASE_URLsqlite://../bakery.db连接 URL 基于graphql目录解析因此../bakery.db指向示例根目录下的数据库文件。若希望以读写模式打开例如用于后续重新跑迁移可改为export DATABASE_URLsqlite://../bakery.db?moderwc2. 启动 GraphQL 服务进入生成好的 GraphQL 工程并直接运行cd graphql cargo run服务启动入口位于 main.rs它通过sea-orm的Database::connect建立连接然后调用query_root::schema构建 Schema最后用axum在默认地址localhost:8000暴露 GraphQL 端点let db Database::connect(*DATABASE_URL) .await .expect(Fail to initialize database connection); let schema sea_orm_seaography_example::query_root::schema(db, *DEPTH_LIMIT, *COMPLEXITY_LIMIT) .unwrap(); let app Router::new() .route(*ENDPOINT, get(graphql_playground).post(graphql_handler)) .with_state(schema); println!(Visit GraphQL Playground at http://{}, *URL); axum::serve(TcpListener::bind(*URL).await.unwrap(), app) .await .unwrap();这里还支持三个可选环境变量均用于 GraphQL 服务的运行期控制环境变量默认值作用URLlocalhost:8000服务监听地址浏览器访问 GraphQL Playground 的入口ENDPOINT/GraphQL 端点路径Playground 与查询请求都挂在它下面DEPTH_LIMIT不限制限制查询嵌套深度防止恶意深嵌套查询COMPLEXITY_LIMIT不限制限制单次查询的复杂度保护后端数据库启动后打开http://localhost:8000即可看到 GraphQL Playground 界面本示例开启了graphql-playgroundfeature。运行示例中的 GraphQL 查询Seaography 为每个实体自动生成对应的根查询字段同时内置了filters过滤、having聚合后过滤、orderBy排序、pagination分页等标准入参。下面三个查询与文档一致可在 Playground 中直接执行验证。查询 1查找巧克力蛋糕及其在售面包店{ cake(filters: { name: { contains: Chocolate } }) { nodes { name price bakery { name } } } }filters支持字符串的contains包含、eq等于、startsWith、endsWith等运算返回结果通过nodes承载数据行并可沿cake - bakery的 belongs_to 关系继续取面包店名称。该查询在仓库测试 query_tests.rs 中被完整断言过预期结果包含 SeaSide Bakery 的两款巧克力蛋糕与 LakeSide Bakery 的一款例如{ cake: { nodes: [ { name: Chocolate Cake, price: 10.25, bakery: { name: SeaSide Bakery } }, { name: Double Chocolate, price: 12.5, bakery: { name: SeaSide Bakery } }, { name: Double Chocolate, price: 12.5, bakery: { name: LakeSide Bakery } } ] } }查询 2查找 Alice 烘焙的所有蛋糕{ cake(having: { baker: { name: { eq: Alice } } }) { nodes { name price baker { nodes { name } } } } }having用于按关联实体条件筛选聚合结果这里要求目标蛋糕必须存在名为Alice的关联面包师经由多对多表cake_baker。值得注意的是外层cake与内层baker的返回结构不同——cake.baker是多对多关系因此以nodes列表形式返回而查询 1 中cake.bakery属于一对一belongs_to关系直接返回对象即可。查询 3面包店 → 蛋糕 → 面包师三级嵌套{ bakery(pagination: { page: { limit: 10, page: 0 } }, orderBy: { name: ASC }) { nodes { name cake { nodes { name price baker { nodes { name } } } } } } }这个查询同时演示了pagination每页 10 条、第 0 页与orderBy按名称升序两种入参并沿bakery - cake - baker三级关系嵌套取数充分体现 Seaography 将 SeaORM 关系模型直接映射为 GraphQL 对象图的能力。注意分页入参中page字段被复用了两次外层为分页对象、内层page为页码使用时需区分。从零搭建完整的生成流程如果不使用仓库自带的生成结果可以按下面四步从头搭建一个属于自己的 SeaORM Seaography GraphQL 工程。第一步准备数据库与迁移进入migration目录其 README 提供了完整说明。设置数据库并应用全部迁移export DATABASE_URLsqlite://../bakery.db?moderwc cd migration cargo run迁移工程包含 7 个迁移文件migration/src从建表到播种依次执行m20230101_000001_create_bakery_table.rs创建bakery表m20230101_000002_create_baker_table.rs创建baker表m20230101_000003_create_cake_table.rs创建cake表m20230101_000004_create_cake_baker_table.rs创建多对多关联表cake_bakerm20230101_000005_create_customer_table.rs创建customer表m20230101_000006_create_order_table.rs创建order表m20230101_000007_create_lineitem_table.rs创建lineitem表m20230102_000001_seed_bakery_data.rs向表中写入 SeaSide Bakery、LakeSide Bakery、Alice、Bob 及各款蛋糕等演示数据。建表迁移使用 SeaORM Migration 的声明式 API例如创建bakery表m20230101_000001_create_bakery_table.rsmanager .create_table( Table::create() .table(bakery) .col(pk_auto(id)) .col(string(name)) .col(double(profit_margin)) .to_owned(), ) .await种子迁移则通过 ActiveModel 插入数据m20230102_000001_seed_bakery_data.rslet bakery bakery::ActiveModel { name: Set(SeaSide Bakery.to_owned()), profit_margin: Set(10.4), ..Default::default() }; let sea Bakery::insert(bakery).exec(db).await?.last_insert_id;迁移 CLI 还支持常用子命令方便管理 Schema 演进命令作用cargo run/cargo run -- up应用所有待执行迁移cargo run -- up -n 10仅应用前 10 个迁移cargo run -- down回滚最近一次迁移cargo run -- down -n 10回滚最近 10 次迁移cargo run -- fresh先删库重建再全部重跑cargo run -- refresh回滚全部后重新应用全部迁移cargo run -- reset回滚全部迁移cargo run -- status查看各迁移执行状态第二步安装两条 CLI 工具链SeaORM Seaography 的代码生成依赖两个 CLI建议使用 2.0 系列的预发布版本cargo install sea-orm-cli^2.0.0-rc cargo install seaography-cli^2.0.0-rcsea-orm-cli负责从数据库反向生成 SeaORM 实体代码seaography-cli负责基于已生成的实体搭建完整的 GraphQL 服务工程axum 框架 async-graphql。第三步生成实体与 GraphQL 工程rm -rf graphql # this entire folder is generated mkdir graphql cd graphql sea-orm-cli generate entity --output-dir ./src/entities --entity-format dense --seaography seaography-cli -o . -e ./src/entities --framework axum sea-orm-seaography-example命令逐条说明sea-orm-cli generate entity连接DATABASE_URL指向的数据库并生成实体--output-dir ./src/entities指定实体输出目录--entity-format dense采用紧凑的实体代码风格--seaography是关键开关它让生成的实体额外携带 Seaography 所需的元数据与关系定义seaography-cli -o . -e ./src/entities --framework axum sea-orm-seaography-example以实体目录为输入生成名为sea-orm-seaography-example的 GraphQL 工程到当前目录Web 框架选择 axum。生成的工程结构与仓库中 graphql 目录一致包括src/entities/从数据库反向生成的 SeaORM 实体baker、bakery、cake、cake_baker 等含mod.rs与prelude.rssrc/query_root.rsSchema 构建逻辑负责把全部实体注册进 GraphQL 并配置深度/复杂度限制src/main.rsaxum 服务入口暴露 Playground 与 GraphQL 端点Cargo.toml依赖配置其中sea-orm开启seaographyfeatureseaography按需开启graphql-playground、with-decimal、with-chrono等特性。query_root.rs是理解生成代码的关键query_root.rspub fn schema_builder( context: static BuilderContext, database: DatabaseConnection, depth: Optionusize, complexity: Optionusize, ) - SchemaBuilder { let mut builder Builder::new(context, database.clone()); builder register_entity_modules(builder); builder .set_depth_limit(depth) .set_complexity_limit(complexity) .schema_builder() .data(database) }从源码结构可以推断Builder遍历所有注册的实体模块把每个实体的查询入口、过滤参数、分页与排序参数以及实体间关系统一翻译成 async-graphql 的动态 Schemaset_depth_limit与set_complexity_limit则把上文的环境变量注入查询保护策略。第四步在自己的工程中调整依赖生成后的Cargo.toml依赖大致如下版本以当前仓库为准[dependencies.sea-orm] features [sqlx-sqlite, runtime-tokio-native-tls, seaography] version ~2.0.3 [dependencies.seaography] features [graphql-playground, with-decimal, with-chrono] version ~2.0.0-rc.3 [dependencies] async-graphql-axum { version 7.0 } axum { version 0.8 } dotenv 0.15.0 tokio { version 1.29.1, features [macros, rt-multi-thread] }几点实战提示sea-orm必须开启seaographyfeature否则query_root.rs依赖的实体注册 API 不可用数据库驱动 feature 要与实际使用的数据库匹配示例中使用 SQLitesqlx-sqliteMySQL/PostgreSQL 项目需相应替换若实体包含Decimal或时间类型字段建议开启with-decimal与with-chrono保证 GraphQL 标量序列化正确本示例的cake.price正是 Decimal 类型查询结果中价格以字符串形式返回如10.25示例中[patch.crates-io] sea-orm { path ../../.. }用于在仓库内联调 SeaORM 本体自己新建工程时应删除该行直接使用 crates.io 发布的版本。验证与测试生成工程自带集成测试可直接验证 GraphQL Schema 与查询结果是否符合预期cd graphql DATABASE_URLsqlite://../bakery.db cargo test测试用例位于 query_tests.rs覆盖了文档中的典型查询test_cake_with_bakery按name.contains(Chocolate)过滤并嵌套取面包店信息test_cake_with_baker按关联面包师姓名过滤以及多级嵌套与排序分页场景。测试内部通过sea_orm::Database::connect连接数据库再调用query_root::schema构建 Schema 后直接executeGraphQL 请求将返回结果与期望 JSON 逐字段比对。这套测试结构可以直接复制到自己的工程中作为 GraphQL API 的回归保障。小结通过本示例可以清晰看到 SeaORM 生态中数据访问层 GraphQL 层的完整协同方式SeaORM 负责用 Rust 类型安全地描述数据库表与关系sea-orm-cli将数据库结构反向生成为实体seaography-cli再把实体工程升级为开箱即用的 GraphQL 服务。整条链路从bakery.db出发几分钟内即可得到支持过滤、排序、分页与多级嵌套查询的 GraphQL API非常适合作为Rust 全栈 GraphQL项目的起步模板。后续可在此基础上继续扩展更换 MySQL/PostgreSQL 驱动、接入认证授权中间件或调整DEPTH_LIMIT/COMPLEXITY_LIMIT以适配更复杂的查询场景。赞分享后端数据库ORM【免费下载链接】sea-orm A powerful relational ORM for Rust项目地址https://gitcode.com/gh_mirrors/se/sea-orm点击查看免费下载相关推荐MovieNight常见问题解决流媒体卡顿、聊天连接失败与权限问题排查MovieNight常见问题解决流媒体卡顿、聊天连接失败与权限问题排查 MovieNight是一款集成聊天功能的单实例视频流媒体服务器专为在线观影群体设计。SeaORM 实战基于 Loco 与 Seaography 的 GraphQL 管理后台——react-admin 示例全解析SeaORM 实战基于 Loco 与 Seaography 的 GraphQL 管理后台——react admin 示例全解析 本篇文章以 sea orm 仓后端数据库ORMNocoBase CLI nb env remove 深度解析安全移除已配置环境与清理本机托管资源NocoBase CLI nb env remove 深度解析安全移除已配置环境与清理本机托管资源 NocoBase CLI nb 通过 env环境机后端数据库ORM上一篇AutoSubs终极指南如何在本地设备上实现专业级AI字幕生成下一篇OpenDesign Airtable 设计系统深度解析从 DESIGN 规范到 tokens.css 的落地实现创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。