如何修复Tauri-Rust结合Diesel与SQLite的数据库缓存问题?
解决方案
1. 修复数据库连接字符串错误
你修改连接时用了sqlite://{}?cache=none的格式,但Diesel的SQLite连接不需要sqlite://前缀,直接传入文件路径即可。正确禁用SQLite缓存的方式是通过连接配置或执行PRAGMA命令:
方式一:执行PRAGMA命令禁用缓存
use diesel::sqlite::SqliteConnection; use diesel::Connection; pub fn establish_connection(path: &str) -> SqliteConnection { let mut conn = SqliteConnection::establish(path) .unwrap_or_else(|_| panic!("Error connecting to database {}", path)); // 执行SQL命令关闭缓存 conn.execute("PRAGMA cache_size = 0; PRAGMA temp_store = MEMORY;") .expect("Failed to disable SQLite cache"); conn }
方式二:用Diesel连接配置设置参数
use diesel::sqlite::SqliteConnection; use diesel::sqlite::SqliteConnectionOptions; use diesel::Connection; pub fn establish_connection(path: &str) -> SqliteConnection { let options = SqliteConnectionOptions::new() .filename(path) .pragma("cache_size", "0") .pragma("temp_store", "MEMORY"); SqliteConnection::establish_with_config(options) .unwrap_or_else(|_| panic!("Error connecting to database {}", path)) }
2. 解决迁移脚本重复插入初始数据的问题
删除数据库文件后仍出现相同数据,核心原因是迁移脚本中每次执行都会插入初始数据,而非仅在表首次创建时执行。
修正迁移脚本逻辑
修改migrations/目录下的迁移文件,给插入语句添加条件判断,确保仅在数据不存在时插入:
-- 仅当表为空时插入初始数据 INSERT INTO pwn_contracts (name) SELECT '初始合约1' WHERE NOT EXISTS (SELECT 1 FROM pwn_contracts); INSERT INTO pwn_contracts (name) SELECT '初始合约2' WHERE NOT EXISTS (SELECT 1 FROM pwn_contracts WHERE name = '初始合约2');
分离初始数据逻辑(可选)
如果不想每次重建数据库都插入初始数据,可将初始数据插入逻辑从迁移脚本中移出,放到应用启动时的条件判断里:
pub fn init_default_data(conn: &mut SqliteConnection) { use crate::schema::pwn_contracts; use diesel::insert_into; use diesel::select; use diesel::dsl::exists; // 检查是否已有数据,无数据则插入 let has_data = select(exists(pwn_contracts::table)) .get_result::<bool>(conn) .unwrap(); if !has_data { insert_into(pwn_contracts::table) .values(&vec![ (pwn_contracts::name.eq("初始合约1")), (pwn_contracts::name.eq("初始合约2")), ]) .execute(conn) .unwrap(); } }
3. 确认Tauri开发模式下的数据库路径
Tauri开发模式中,应用数据目录可能和你手动删除的路径不一致,可打印实际路径确认:
pub fn contract_list(db_path: String) -> Vec<Contract> { println!("实际数据库路径: {}", db_path); // 打印路径,验证是否删除了正确文件 let mut connection = establish_connection(&db_path); pwn_contracts::dsl::pwn_contracts .select(pwn_contracts::all_columns) .load::<Contract>(&mut connection) .expect("Loading contracts failed") }
推荐使用Tauri提供的专属数据目录,避免路径混乱:
use tauri::api::path::data_dir; use std::path::PathBuf; fn get_db_path() -> String { let mut data_dir = data_dir().expect("获取数据目录失败"); data_dir.push("你的应用名称"); std::fs::create_dir_all(&data_dir).expect("创建数据目录失败"); data_dir.push("app.db"); data_dir.to_str().unwrap().to_string() }
内容的提问来源于stack exchange,提问作者Robert
相关产品推荐
相关产品推荐

