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 次
