Rust 用 sea-orm 做类型安全 ORM:实体定义、关联查询与数据库迁移

test12026-10-200 次阅读

为什么选 sea-orm

diesel 是编译期 DSL 的标杆,但它偏同步、写法重。sea-orm 是异步优先、derive 驱动的 ORM,底层基于 sqlx,天然契合 tokio 生态,实体用属性宏生成,字段类型在编译期就锁死。

用宏定义实体

DeriveEntityModel 自动生成列与 Model/ActiveModel,belongs_to 一行声明关联关系。

use sea_orm::entity::prelude::*;

#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
#[sea_orm(table_name = "posts")]
pub struct Model {
    #[sea_orm(primary_key)]
    pub id: i32,
    pub title: String,
    pub author_id: i32,
}

#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {
    #[sea_orm(
        belongs_to = "super::author::Entity",
        from = "Column::AuthorId",
        to = "super::author::Column::Id"
    )]
    Author,
}

impl ActiveModelBehavior for ActiveModel {}

查询与关联加载

find_with_related 一次性把帖子连同作者拉出来,返回类型是 Vec<(post::Model, Vec<author::Model>)>,类型全程可追溯。

use sea_orm::{EntityTrait, QuerySelect, Related};

let rows = Post::find()
    .find_with_related(Author)
    .all(&db)
    .await?;

for (post, authors) in rows {
    println!("{} 由 {} 位作者参与", post.title, authors.len());
}

用迁移守住表结构

sea-orm-cli 生成可回滚的 Migration,up 建表、down 删表,和 golang-migrate 思路一致但用 Rust 代码描述。

use sea_orm_migration::prelude::*;

pub struct Migration;
impl MigrationName for Migration {
    fn name(&self) -> &str { "m20240101_000001_create_post" }
}

#[async_trait::async_trait]
impl MigrationTrait for Migration {
    async fn up(&self, m: &SchemaManager) -> Result<(), DbErr> {
        m.create_table(
            Table::create()
                .table(Post::Table)
                .col(ColumnDef::new(Post::Id).integer().primary_key())
                .col(ColumnDef::new(Post::Title).string().not_null())
                .to_owned(),
        ).await
    }
    async fn down(&self, m: &SchemaManager) -> Result<(), DbErr> {
        m.drop_table(Table::drop().table(Post::Table).to_owned()).await
    }
}

和 diesel 怎么取舍

要 async、要和 axum/tokio 无缝衔接、想要 derive 式实体,选 sea-orm;追求极致同步性能、接受较重的 DSL,diesel 依然稳。两者都是类型安全,不会让你把字段名拼错成运行时报错。

小结

  • sea-orm 用 derive 定义实体,字段类型编译期锁定。
  • find_with_related 把关联查询做成强类型返回。
  • 迁移用 Rust 代码描述 up/down,可回滚。
  • 异步生态首选 sea-orm,同步重性能选 diesel。
T

test1

文章作者

为什么选 sea-orm diesel 是编译期 DSL 的标杆,但它偏同步、写法重。sea-orm 是异步优先、de...

分类
技术
发布时间
2026-10-20
字数
约 2139 字
阅读
0 次