Rust构建web应用报sqlite3多包链接错误,该选择哪个版本的rusqlite
问题根源
报错的核心原因是你同时引入了两套不同的SQLite原生绑定依赖:
- 你手动引入的
rusqlite0.23版本依赖libsqlite3-sys v0.18.0链接原生sqlite3库 - 你引入的
r2d2-sqlite3包底层依赖旧版本的sqlite3crate,对应的sqlite3-sys v0.12.0也会链接原生sqlite3库
Rust的cargo规则不允许同一个原生库被多个包重复链接,因此触发了该报错。
修复方案
不要使用已经停止维护的r2d2-sqlite3包,直接使用rusqlite官方内置的r2d2连接池集成功能即可,修改如下:
1. 修改Cargo.toml配置
删掉r2d2-sqlite3依赖,给rusqlite启用r2d2特性:
[package] name = "todo" version = "0.1.0" edition = "2018" [dependencies] actix-web = "4.0.0-beta.3" actix-rt = "2.2.0" thiserror = "1.0.29" askama = "0.10.5" rusqlite = { version = "0.23", features = ["bundled", "r2d2"] } r2d2 = "0.8.9"
2. 修改main.rs对应代码
调整连接池管理器的导入路径,同时删除conn.execute后多余的expect调用(?已经完成了错误抛出,返回的执行行数不需要再unwrap):
use actix_web::{get, App, HttpResponse, HttpServer, ResponseError}; use thiserror::Error; use askama::Template; use r2d2::Pool; // 修改导入路径为rusqlite内置的r2d2管理器 use rusqlite::r2d2::SqliteConnectionManager; use rusqlite::params; struct TodoEntry { id: u32, text: String, } #[derive(Template)] #[template(path = "index.html")] struct IndexTemplate { entries: Vec<TodoEntry>, } #[derive(Error, Debug)] enum MyError { #[error("Failed to render HTML")] AskamaError(#[from] askama::Error), } impl ResponseError for MyError {} #[get("/")] async fn index() -> Result<HttpResponse, MyError> { let mut entries = Vec::new(); entries.push(TodoEntry { id: 1, text: "First entry".to_string(), }); entries.push(TodoEntry { id: 2, text: "Second entry".to_string(), }); let html = IndexTemplate { entries }; let response_body = html.render()?; Ok(HttpResponse::Ok() .content_type("text/html") .body(response_body)) } #[actix_rt::main] async fn main() -> Result<(), actix_web::Error> { let manager = SqliteConnectionManager::file("todo.db"); let pool = Pool::new(manager).expect("Failed to initialize the connection pool."); let conn = pool .get() .expect("Failed to get the connection from the pool."); conn.execute( "CREATE TABLE IF NOT EXISTS todo ( id INTEGER PRIMARY KEY AUTOINCREMENT, text TEXT NOT NULL )", params![], )?; HttpServer::new(move || App::new().service(index)) .bind("127.0.0.1:8080")? .run() .await?; Ok(()) }
修改后执行cargo clean清理之前的构建缓存,再运行cargo run即可正常编译运行。
内容的提问来源于stack exchange,提问作者Pierogi
相关产品推荐
相关产品推荐

