rust 结构体如何与表字段对上

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-postgresmysql_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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

leijmdas

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值