Rust 结构体与数据库表字段的对应,通常通过 ORM/Derive 宏 或 手动实现 trait 来完成。以下是主流方案的具体做法:
1. SQLx(编译时检查,最常用)
使用 FromRow derive 宏,通过 #[sqlx(rename = "...")] 精确映射字段名。
rust
use sqlx::FromRow;
#[derive(FromRow)]
struct User {
id: i64,
#[sqlx(rename = "user_name")] // 表字段是 user_name,结构体字段是 username
username: String,
#[sqlx(rename = "created_at")]
created_at: chrono::NaiveDateTime,
// 忽略表中有但结构体不需要的字段
#[sqlx(default)]
avatar: Option<String>,
}
查询时自动映射:
rust
let user: User = sqlx::query_as::<_, User>("SELECT id, user_name, created_at FROM users")
.fetch_one(&pool)
.await?;
2. Diesel(传统强类型 ORM)
先定义表 schema(通常用 diesel setup + diesel migration 自动生成 schema.rs),再用 Queryable / Insertable。
schema.rs(自动生成或手写):
rust
diesel::table! {
users (id) {
id -> Int8,
user_name -> Varchar,
created_at -> Timestamp,
}
}
结构体映射:
rust
use diesel::{Queryable, Insertable};
use crate::schema::users;
#[derive(Queryable, Insertable)]
#[diesel(table_name = users)]
struct User {
id: i64,
#[diesel(column_name = user_name)] // 字段名不一致时
username: String,
created_at: chrono::NaiveDateTime,
}
3. Sea-ORM(异步、类似 ActiveRecord)
rust
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
#[sea_orm(table_name = "users")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i64,
#[sea_orm(column_name = "user_name", column_type = "String(Some(255))")]
pub username: String,
pub created_at: DateTime,
}
// 自动生成关联
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
4. 手动实现(不依赖 ORM)
如果你用底层驱动(如 tokio-postgres、mysql_async),手动实现转换:
rust
use tokio_postgres::Row;
struct User {
id: i64,
username: String,
}
impl From<&Row> for User {
fn from(row: &Row) -> Self {
Self {
id: row.get("id"),
username: row.get("user_name"), // 直接按表字段名 get
}
}
}
关键对照表
表格
| 场景 | 解决方案 |
|---|---|
| 字段名完全一致(snake_case) | 直接用 derive,无需额外标注 |
字段名不一致(如表 user_name → 结构体 username) | 用 #[sqlx(rename)] / #[diesel(column_name)] / #[sea_orm(column_name)] |
| 表中有字段但结构体不需要 | #[sqlx(skip)] 或不用 select 该字段 |
| 结构体有字段但表中没有 | 用 #[sqlx(default)] 或 #[diesel(skip_insertion)] |
| 类型不匹配 | 自定义类型 + 实现 Type / FromSql trait |
建议:新项目推荐 SQLx(#[derive(FromRow)] + #[sqlx(rename)]),它在编译期检查 SQL 语法和字段类型,同时保持灵活性。如果偏好更重的 ORM 抽象,选 Sea-ORM。

1100

被折叠的 条评论
为什么被折叠?



