SQLx 集成 #
添加依赖 #
toml
[dependencies]
sqlx = { version = "0.7", features = ["runtime-tokio", "postgres", "chrono", "uuid"] }
连接池配置 #
rust
use sqlx::postgres::PgPoolOptions;
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let database_url = std::env::var("DATABASE_URL").expect("DATABASE_URL must be set");
let pool = PgPoolOptions::new()
.max_connections(10)
.connect(&database_url)
.await
.expect("Failed to create pool");
HttpServer::new(move || {
App::new()
.app_data(web::Data::new(pool.clone()))
})
.bind("127.0.0.1:8080")?
.run()
.await
}
编译时检查 #
SQLx 在编译时验证 SQL 查询,需要设置 DATABASE_URL 环境变量。
创建表 #
sql
CREATE TABLE users (
id SERIAL PRIMARY KEY,
name VARCHAR NOT NULL,
email VARCHAR NOT NULL,
created_at TIMESTAMP DEFAULT NOW()
);
模型定义 #
rust
use chrono::NaiveDateTime;
use serde::{Deserialize, Serialize};
use sqlx::FromRow;
#[derive(Debug, Clone, Serialize, Deserialize, FromRow)]
pub struct User {
pub id: i32,
pub name: String,
pub email: String,
pub created_at: NaiveDateTime,
}
#[derive(Debug, Deserialize)]
pub struct CreateUser {
pub name: String,
pub email: String,
}
CRUD 操作 #
查询所有 #
rust
use sqlx::PgPool;
pub async fn get_all_users(pool: &PgPool) -> Result<Vec<User>, sqlx::Error> {
sqlx::query_as!(User, "SELECT id, name, email, created_at FROM users ORDER BY id")
.fetch_all(pool)
.await
}
按 ID 查询 #
rust
pub async fn get_user_by_id(pool: &PgPool, id: i32) -> Result<Option<User>, sqlx::Error> {
sqlx::query_as!(
User,
"SELECT id, name, email, created_at FROM users WHERE id = $1",
id
)
.fetch_optional(pool)
.await
}
创建 #
rust
pub async fn create_user(pool: &PgPool, user: &CreateUser) -> Result<User, sqlx::Error> {
sqlx::query_as!(
User,
r#"
INSERT INTO users (name, email)
VALUES ($1, $2)
RETURNING id, name, email, created_at
"#,
user.name,
user.email
)
.fetch_one(pool)
.await
}
更新 #
rust
pub async fn update_user(
pool: &PgPool,
id: i32,
name: Option<&str>,
email: Option<&str>,
) -> Result<Option<User>, sqlx::Error> {
sqlx::query_as!(
User,
r#"
UPDATE users
SET name = COALESCE($1, name),
email = COALESCE($2, email)
WHERE id = $3
RETURNING id, name, email, created_at
"#,
name,
email,
id
)
.fetch_optional(pool)
.await
}
删除 #
rust
pub async fn delete_user(pool: &PgPool, id: i32) -> Result<bool, sqlx::Error> {
let result = sqlx::query!("DELETE FROM users WHERE id = $1", id)
.execute(pool)
.await?;
Ok(result.rows_affected() > 0)
}
完整示例 #
rust
use actix_web::{web, App, HttpResponse, HttpServer, Responder};
use serde::{Deserialize, Serialize};
use sqlx::{FromRow, PgPool, postgres::PgPoolOptions};
#[derive(Debug, Serialize, Deserialize, FromRow)]
struct User {
id: i32,
name: String,
email: String,
}
#[derive(Deserialize)]
struct CreateUser {
name: String,
email: String,
}
#[actix_web::get("/users")]
async fn list_users(pool: web::Data<PgPool>) -> impl Responder {
match sqlx::query_as!(User, "SELECT id, name, email FROM users")
.fetch_all(pool.get_ref())
.await
{
Ok(users) => HttpResponse::Ok().json(users),
Err(e) => HttpResponse::InternalServerError()
.json(serde_json::json!({ "error": e.to_string() })),
}
}
#[actix_web::post("/users")]
async fn create_user(pool: web::Data<PgPool>, body: web::Json<CreateUser>) -> impl Responder {
match sqlx::query_as!(
User,
"INSERT INTO users (name, email) VALUES ($1, $2) RETURNING id, name, email",
body.name,
body.email
)
.fetch_one(pool.get_ref())
.await
{
Ok(user) => HttpResponse::Created().json(user),
Err(e) => HttpResponse::InternalServerError()
.json(serde_json::json!({ "error": e.to_string() })),
}
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let pool = PgPoolOptions::new()
.max_connections(5)
.connect("postgres://user:pass@localhost/db")
.await
.expect("Failed to create pool");
HttpServer::new(move || {
App::new()
.app_data(web::Data::new(pool.clone()))
.service(list_users)
.service(create_user)
})
.bind("127.0.0.1:8080")?
.run()
.await
}
下一步 #
继续学习 SeaORM 集成,了解现代化异步 ORM!
最后更新:2026-03-29