升级Diesel v2后Rust项目查询报错:类型可变不匹配
问题:Diesel v2升级后数据库查询报错(类型不匹配)
升级Diesel到v2版本后,数据库查询功能无法正常运行,出现以下类型不匹配错误:
error[E0308]: mismatched types --> src/u/r/api/products/articles.rs:17:69 | 17 | let query = web::block(move || articles::table.load::<Articles>(&*connection).unwrap()).await; | ---------------- ^^^^^^^^^^^^ types differ in mutability | | | arguments to this function are incorrect | = note: expected mutable reference `&mut _` found reference `&PgConnection` note: associated function defined here --> /Users/b/.cargo/registry/src/github.com/diesel-2.0.2/src/query_dsl/mod.rs:1497:8 | 1497 | fn load<'query, U>(self, conn: &mut Conn) -> QueryResult<Vec<U>> | ^^^^
相关代码
路由处理代码
use crate::u::db::connection::DbPool; use actix_web::{get, web, HttpResponse, Responder}; #[get("/product/articles")] pub async fn list(db_pool: web::Data<DbPool>) -> impl Responder { use crate::u::db::models::products::Articles; use crate::u::db::schemas::products::articles; let connection = db_pool.get(); if let Err(e) = connection { return HttpResponse::InternalServerError().body(format!("E1-{:?}", e)); } let connection = connection.unwrap(); let query = web::block(move || articles::table.load::<Articles>(&*connection).unwrap()).await; if let Err(e) = query { return HttpResponse::InternalServerError().body(format!("E2-{:?}", e)); } let q = query.expect("oops not Ok"); HttpResponse::Ok().json(q) }
模型定义(models/products.rs)
use chrono::{DateTime, Utc}; use uuid::Uuid; use crate::u::db::schemas::products::*; #[derive(Queryable, Debug, Identifiable, serde::Serialize, serde::Deserialize)] #[table_name = "articles"] #[primary_key(prod_art_pvt_uuid)] pub struct Articles { pub prod_art_pvt_uuid: Uuid, pub prod_art_pub_uuid: Uuid, pub prod_article_pub_id: i32, pub t: DateTime<Utc>, }
数据库连接池配置(db/connection.rs)
use crate::u::config; use diesel::pg::PgConnection; use diesel::r2d2::ConnectionManager; use r2d2::Pool; pub type DbPool = r2d2::Pool<ConnectionManager<PgConnection>>; pub fn get_pool() -> DbPool { let url: String = config::get("database_url"); println!("Connecting to database..."); let manager = ConnectionManager::<PgConnection>::new(url); Pool::builder() .build(manager) .expect("Failed to create database connection pool."); }
修复方案
核心原因
Diesel v2版本对数据库连接的可变性做了强制调整:所有涉及数据库交互的方法(如load、get_result等)都要求传入可变连接引用,因为底层操作需要修改连接的内部状态(比如事务跟踪、查询缓存),不再支持不可变引用。
具体修改
只需要调整路由处理代码中调用load方法时的连接引用,将不可变引用改为可变引用:
修改后的路由处理代码:
use crate::u::db::connection::DbPool; use actix_web::{get, web, HttpResponse, Responder}; #[get("/product/articles")] pub async fn list(db_pool: web::Data<DbPool>) -> impl Responder { use crate::u::db::models::products::Articles; use crate::u::db::schemas::products::articles; let connection = db_pool.get(); if let Err(e) = connection { return HttpResponse::InternalServerError().body(format!("E1-{:?}", e)); } let mut connection = connection.unwrap(); // 添加mut关键字,使连接可变 // 传入可变引用替代原不可变引用 let query = web::block(move || articles::table.load::<Articles>(&mut connection).unwrap()).await; if let Err(e) = query { return HttpResponse::InternalServerError().body(format!("E2-{:?}", e)); } let q = query.expect("oops not Ok"); HttpResponse::Ok().json(q) }
关键修改点
- 声明连接变量时添加
mut关键字,让连接本身具备可变性; - 调用
load方法时传入&mut connection可变引用,匹配Diesel v2的方法签名要求。
修改后代码即可符合Diesel v2的类型规范,正常执行数据库查询。
内容的提问来源于stack exchange,提问作者Nkk
相关产品推荐
相关产品推荐

