You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

升级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)
}

关键修改点

  1. 声明连接变量时添加mut关键字,让连接本身具备可变性;
  2. 调用load方法时传入&mut connection可变引用,匹配Diesel v2的方法签名要求。

修改后代码即可符合Diesel v2的类型规范,正常执行数据库查询。

内容的提问来源于stack exchange,提问作者Nkk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 23:10:25