楼层: 首页/ 软件技术/ Rust 后端技术栈/ 数据库访问:SQLx 与 SeaORM
03

数据库访问:SQLx 与 SeaORM

SQLx & SeaORM · Compile-time Checked SQL

Rust 数据库圈两大主流:SQLx——你写 SQL,它在编译期帮你检查语法对不对、参数类型对不对,不用 ORM;SeaORM——ActiveRecord 风格的 ORM,类似 Django ORM,不想写 SQL 就用它。本章两个都讲,你按口味选。

SQLx:编译期检查 SQL 的异步数据库库

论SQLx 最爽的一点

普通 ORM 是运行时才发现 SQL 写错了——你接口上线了,用户点一下报 500。SQLx 是编译期就把你的 SQL 发给数据库验证:语法错了、表不存在、列名拼错了、参数类型不匹配,cargo build 直接报错。这是其他语言做梦都想要的能力。

支持 MySQL / PostgreSQL / SQLite,全异步,连接池开箱即用。对标 Java 的 MyBatis,但比 MyBatis 早发现错误十年。

Cargo.toml(以 PostgreSQL 为例)

sqlx = { version = "0.8", features = ["runtime-tokio-rustls", "postgres", "chrono", "uuid", "macros"] }

连接池 + CRUD

use sqlx::{postgres::PgPoolOptions, Row}; use serde::Serialize; // 实体:用 FromRow derive,行自动映射成结构体 #[derive(Debug, Serialize, sqlx::FromRow)] struct User { id: i64, name: String, email: String, } #[tokio::main] async fn main() -> anyhow::Result<()> { // 1. 创建连接池(对标 HikariCP) let pool = PgPoolOptions::new() .max_connections(10) .connect("postgres://postgres:postgres@localhost/app") .await?; // 2. query! 宏:编译期检查 SQL(需要数据库在线或 SQLX_OFFLINE) let rows = sqlx::query!( "SELECT id, name, email FROM users WHERE email = $1", "a@b.com" ).fetch_all(&pool).await?; for r in rows { println!("{} {}", r.id, r.name); } // 3. query_as! 直接映射到结构体 let user: Option<User> = sqlx::query_as::<_, User>( "SELECT id, name, email FROM users WHERE id = $1" ).bind(1) .fetch_optional(&pool) .await?; // 4. 事务:begin / commit / rollback(对标 @Transactional) let mut tx = pool.begin().await?; sqlx::query("INSERT INTO users(name, email) VALUES ($1, $2)") .bind("Tom") .bind("tom@x.com") .execute(&mut *tx).await?; tx.commit().await?; Ok(()) }

sqlx-cli 与离线编译

query! 宏在编译期要连数据库验证 SQL。CI 环境不一定有数据库,这时候用离线模式:本地跑一次 cargo sqlx prepare,把查询缓存到 .sqlx/ 目录,提交到 git。CI 上设 SQLX_OFFLINE=true,就不连数据库也能编译。

# 安装命令行工具 cargo install sqlx-cli --no-default-features --features rustls,postgres # 创建迁移文件 sqlx migrate add create_users_table # 执行迁移 sqlx migrate run # 生成离线查询缓存(CI 前必跑) cargo sqlx prepare # CI 上:不连数据库也能编译 SQLX_OFFLINE=true cargo build --release

SeaORM:写不来 SQL 就用 ORM

SeaORM 是 Rust 里最成熟的 ORM,ActiveRecord 风格。定义 Entity,然后用链式 API 查询,不用写一句 SQL。适合业务模型复杂、团队不想写 SQL 的场景。

// src/entity/user.rs —— 定义实体(对标 JPA @Entity) use sea_orm::entity::prelude::*; #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize)] #[sea_orm(table_name = "users")] pub struct Model { #[sea_orm(primary_key)] pub id: i64, pub name: String, pub email: String, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] pub enum Relation {} impl ActiveModelBehavior for ActiveModel {} // 查询:find + filter + order_by + paginate use sea_orm::{Database, EntityTrait, QueryFilter, QueryOrder, ColumnTrait}; let db = Database::connect("postgres://...").await?; // WHERE name LIKE '%Tom%' ORDER BY id DESC LIMIT 10 let users = Entity::find() .filter(Column::Name.contains("Tom")) .order_by_desc(Column::Id) .limit(10) .all(&db).await?; // 插入一条 let new_user = ActiveModel { name: Set("Tom".into()), email: Set("tom@x.com".into()), ..Default::default() }; new_user.save(&db).await?;

Diesel:老牌编译期查询构建器(了解即可)

Diesel 是 Rust 最早一代数据库生态主力,主打"编译期把查询语法和字段类型全查一遍"。它和 sqlx 的共同点是编译期安全,但路线不同:sqlx 让你写裸 SQL 再校验,Diesel 用 DSL 拼查询。新项目更推荐 sqlx + SeaORM,但面试/老项目可能遇到 Diesel,认得就行。

// Diesel 是同步的(不基于 Tokio),用 schema!! 宏映射表结构 table! users { id -> Int8, name -> Varchar, } use users::dsl::*; // DSL 拼查询,类型在编译期就对齐 let results = users .filter(name.like("%Tom%")) .order(id.desc()) .limit(10) .load::<User>(&mut conn)?; // conn 是同步连接
三种数据库栈怎么选
栈特点适合
sqlx写裸 SQL,编译期校验,异步主力:业务复杂、想掌 SQL
SeaORMActiveRecord ORM,异步,链式 API不想写 SQL、模型驱动
DieselDSL 查询构建器,同步,老牌维护老项目;新项目少用

NoSQL:Redis 与 MongoDB

场景推荐 crate说明
Redis 缓存redis(带 tokio-comp feature)异步客户端,支持 SET/GET/PubSub/Stream
MongoDBmongodb(官方驱动)官方维护,异步,BSON 文档模型
向量检索qdrant-clientRust 写的向量库,AI 页细讲
use redis::{AsyncCommands, Client}; let client = Client::open("redis://127.0.0.1/")?; let mut con = client.get_multiplexed_async_connection().await?; con::set_ex("greeting", "hello", 60).await?; let v: String = con::get("greeting").await?; println!("{v}");
记
本章小结

① SQLx 写 SQL,编译期检查;SeaORM 写 ORM,链式 API。团队里有 SQL 高手就 SQLx,业务模型复杂就 SeaORM。

② 连接池用 PgPoolOptions,事务用 begin()/commit(),迁移用 sqlx migrate,CI 用 SQLX_OFFLINE=true。

③ Redis 用 redis crate,MongoDB 用官方 mongodb crate。