Diesel 集成 #

添加依赖 #

toml
[dependencies]
diesel = { version = "2", features = ["postgres", "r2d2", "chrono"] }
dotenvy = "0.15"

[dependencies.actix-web]
version = "4"

配置 #

安装 Diesel CLI #

bash
cargo install diesel_cli --no-default-features --features postgres

初始化 #

bash
diesel setup
diesel migration generate create_users

数据库连接 #

rust
use diesel::pg::PgConnection;
use diesel::r2d2::{self, ConnectionManager};
use std::env;

pub type DbPool = r2d2::Pool<ConnectionManager<PgConnection>>;

pub fn establish_connection() -> DbPool {
    let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
    let manager = ConnectionManager::<PgConnection>::new(database_url);
    
    r2d2::Pool::builder()
        .build(manager)
        .expect("Failed to create pool.")
}

模型定义 #

Schema #

rust
diesel::table! {
    users (id) {
        id -> Int4,
        name -> Varchar,
        email -> Varchar,
        created_at -> Timestamp,
    }
}

Model #

rust
use chrono::NaiveDateTime;
use diesel::prelude::*;

#[derive(Queryable, Selectable, Debug, Clone)]
#[diesel(table_name = crate::schema::users)]
pub struct User {
    pub id: i32,
    pub name: String,
    pub email: String,
    pub created_at: NaiveDateTime,
}

#[derive(Insertable)]
#[diesel(table_name = crate::schema::users)]
pub struct NewUser<'a> {
    pub name: &'a str,
    pub email: &'a str,
}

CRUD 操作 #

创建 #

rust
use crate::schema::users;
use diesel::prelude::*;

pub fn create_user(conn: &mut PgConnection, name: &str, email: &str) -> QueryResult<User> {
    let new_user = NewUser { name, email };
    
    diesel::insert_into(users::table)
        .values(&new_user)
        .returning(User::as_returning())
        .get_result(conn)
}

查询 #

rust
pub fn get_all_users(conn: &mut PgConnection) -> QueryResult<Vec<User>> {
    users::table
        .select(User::as_select())
        .load(conn)
}

pub fn get_user_by_id(conn: &mut PgConnection, user_id: i32) -> QueryResult<Option<User>> {
    users::table
        .find(user_id)
        .select(User::as_select())
        .first(conn)
        .optional()
}

更新 #

rust
pub fn update_user(
    conn: &mut PgConnection,
    user_id: i32,
    name: Option<&str>,
    email: Option<&str>,
) -> QueryResult<User> {
    diesel::update(users::find(users::table, user_id))
        .set((
            users::name.eq(name.unwrap_or_default()),
            users::email.eq(email.unwrap_or_default()),
        ))
        .returning(User::as_returning())
        .get_result(conn)
}

删除 #

rust
pub fn delete_user(conn: &mut PgConnection, user_id: i32) -> QueryResult<usize> {
    diesel::delete(users::find(users::table, user_id))
        .execute(conn)
}

在 Actix Web 中使用 #

rust
use actix_web::{web, App, HttpResponse, HttpServer, Responder};
use diesel::prelude::*;

async fn list_users(pool: web::Data<DbPool>) -> impl Responder {
    let mut conn = pool.get().unwrap();
    
    match get_all_users(&mut conn) {
        Ok(users) => HttpResponse::Ok().json(users),
        Err(_) => HttpResponse::InternalServerError().finish(),
    }
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    let pool = establish_connection();
    
    HttpServer::new(move || {
        App::new()
            .app_data(web::Data::new(pool.clone()))
            .route("/users", web::get().to(list_users))
    })
    .bind("127.0.0.1:8080")?
    .run()
    .await
}

下一步 #

继续学习 SQLx 集成,了解异步查询方案!

最后更新:2026-03-29