Rust+Actix-Web构建REST API遇LoadConnection trait未实现错误求助
问题:Rust + Actix-Web + Diesel 2.0 构建REST API时的LoadConnection trait错误
我正在用Rust和Actix-Web构建REST API,使用Diesel 2.0.3操作PostgreSQL数据库,但运行时持续报错。相关代码如下:
main.rs(连接池配置)
#[actix_web::main] async fn main() -> std::io::Result<()> { // Loading .env into environment variable. dotenv::dotenv().ok(); env_logger::init_from_env(env_logger::Env::new().default_filter_or("info")); // set up database connection pool let database_url = std::env::var("DATABASE_URL").expect("DATABASE_URL"); let manager = ConnectionManager::<PgConnection>::new(database_url); let pool: DbPool = r2d2::Pool::builder() .test_on_check_out(true) .build(manager) .expect("Could not build connection pool"); let port = std::env::var("PORT").expect("$PORT is not set."); HttpServer::new(move || { App::new() .app_data(web::Data::new(pool.clone())) .wrap(middleware::Logger::default()) .route("/", web::get().to(|| async { "Actix REST API" })) .service(handlers::common::houses::index) }) .bind(("0.0.0.0", port.parse().unwrap()))? .run() .await }
schema定义
diesel::table! { houses (id) { id -> Int4, user_id -> Varchar, street -> Varchar, figure -> Varchar, floor -> Varchar, create_date -> Timestamp, update_date -> Timestamp, is_deleted -> Bool, } }
House模型
#[derive(Debug, Serialize, Deserialize, Queryable)] pub struct House { pub id: i32, pub user_id: String, pub street: String, pub figure: String, pub floor: String, pub create_date: chrono::NaiveDateTime, pub update_date: chrono::NaiveDateTime, pub is_deleted: bool, }
handler代码
#[get("/houses")] async fn index(pool: web::Data<DbPool>) -> Result<HttpResponse, Error> { let houses = web::block(move || { let conn = &pool.get()?; find_all(&conn) }) .await? .map_err(actix_web::error::ErrorInternalServerError)?; Ok(HttpResponse::Ok().json(houses)) } fn find_all(conn: &PgConnection) -> Result<Vec<House>, DbError> { use crate::schemas::common::houses::houses::dsl::*; let items =houses.load::<House>(&mut conn)?; Ok(items) }
依赖配置
[dependencies] actix-web = "4" chrono = { version = "0.4.19", features = ["serde"] } diesel = { version = "2.0.3", features = ["postgres", "r2d2", "chrono"] } dotenv = "0.15.0" env_logger = "0.10.0" serde = { version = "1.0.136", features = ["derive"] } serde_json = "1.0"
错误信息
error[E0277]: the trait bound `&diesel::PgConnection: LoadConnection` is not satisfied src\handlers\common\houses.rs:25:37 | 25 | let items =houses.load::<House>(&mut conn)?; | ---- -^^^^^^^^ | | | the trait `LoadConnection` is not implemented for `&diesel::PgConnection` help: consider removing the leading `&`-reference required by a bound introduced by this call | note: required for `table` to implement `LoadQuery<'_, &diesel::PgConnection, House>` note: required by a bound in `diesel::RunQueryDsl::load`
解决方案
这个错误的核心是Diesel 2.0对连接的借用规则做了调整,代码中出现了多层引用的冲突问题:
index函数中,pool.get()返回连接实例,你取了它的不可变引用&conn传给find_allfind_all里又试图对这个不可变引用加可变借用&mut conn,导致类型不匹配,不符合LoadConnectiontrait的要求
修改步骤如下:
1. 调整连接获取方式
在index的web::block闭包中,直接获取可变连接的所有权:
#[get("/houses")] async fn index(pool: web::Data<DbPool>) -> Result<HttpResponse, Error> { let houses = web::block(move || { let mut conn = pool.get()?; // 获取可变连接的所有权 find_all(&mut conn) }) .await? .map_err(actix_web::error::ErrorInternalServerError)?; Ok(HttpResponse::Ok().json(houses)) }
2. 修改find_all函数的参数和调用
让find_all接收可变连接引用,调用load时直接传递该引用:
fn find_all(conn: &mut PgConnection) -> Result<Vec<House>, DbError> { use crate::schemas::common::houses::houses::dsl::*; let items = houses.load::<House>(conn)?; // 直接传可变引用,无需额外加&mut Ok(items) }
原因说明
Diesel 2.0中,load方法需要的是可变的连接引用,你之前的代码把连接变成了&mut &PgConnection类型,完全不符合约束要求。通过调整连接的获取和传递方式,让conn成为&mut PgConnection类型,就能满足LoadConnection trait的实现条件。
内容的提问来源于stack exchange,提问作者A G
相关产品推荐
相关产品推荐

