fix: 修复数据库迁移问题
- 将表创建和索引创建逻辑从仓储初始化方法移到迁移系统 - 移除 outfit_image_repository.rs 中的 init_tables 表创建逻辑 - 确保所有数据库结构变更通过迁移系统统一管理 - 修复 comfyui_prompt_id 索引创建时机问题 这样可以避免在旧数据库上创建索引时找不到字段的错误。
This commit is contained in:
parent
4b20f69560
commit
676effdab4
|
|
@ -82,13 +82,11 @@ impl ModelService {
|
|||
pub fn get_all_models(
|
||||
repository: &ModelRepository,
|
||||
) -> Result<Vec<Model>> {
|
||||
println!("ModelService::get_all_models 开始执行");
|
||||
let result = repository.get_all()
|
||||
.map_err(|e| {
|
||||
println!("repository.get_all() 失败: {}", e);
|
||||
anyhow!("获取模特列表失败: {}", e)
|
||||
});
|
||||
println!("ModelService::get_all_models 执行完成,结果: {:?}", result.is_ok());
|
||||
result
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -171,7 +171,6 @@ impl ModelRepository {
|
|||
|
||||
/// 获取所有模特
|
||||
pub fn get_all(&self) -> Result<Vec<Model>> {
|
||||
println!("ModelRepository::get_all 开始执行");
|
||||
|
||||
// 首先获取所有模特的基本信息
|
||||
let mut models = {
|
||||
|
|
@ -202,11 +201,8 @@ impl ModelRepository {
|
|||
|
||||
let mut models = Vec::new();
|
||||
for (index, model) in model_iter.enumerate() {
|
||||
println!("处理第 {} 个模特记录", index + 1);
|
||||
println!("开始解析模特数据...");
|
||||
let model = match model {
|
||||
Ok(m) => {
|
||||
println!("模特数据解析成功: {}", m.name);
|
||||
m
|
||||
}
|
||||
Err(e) => {
|
||||
|
|
@ -215,17 +211,14 @@ impl ModelRepository {
|
|||
}
|
||||
};
|
||||
models.push(model);
|
||||
println!("第 {} 个模特记录处理完成", index + 1);
|
||||
}
|
||||
models
|
||||
}; // 释放数据库连接锁
|
||||
|
||||
// 然后为每个模特加载照片信息(避免嵌套锁)
|
||||
for model in &mut models {
|
||||
println!("开始加载模特 {} 的照片信息", model.id);
|
||||
model.photos = match self.get_photos(&model.id) {
|
||||
Ok(photos) => {
|
||||
println!("照片信息加载成功,共 {} 张照片", photos.len());
|
||||
photos
|
||||
}
|
||||
Err(e) => {
|
||||
|
|
@ -235,11 +228,6 @@ impl ModelRepository {
|
|||
}
|
||||
};
|
||||
}
|
||||
|
||||
println!(
|
||||
"ModelRepository::get_all 执行完成,返回 {} 个模特",
|
||||
models.len()
|
||||
);
|
||||
Ok(models)
|
||||
}
|
||||
|
||||
|
|
@ -517,7 +505,6 @@ impl ModelRepository {
|
|||
description, tags, is_cover, created_at
|
||||
FROM model_photos WHERE model_id = ?1 ORDER BY created_at DESC",
|
||||
)?;
|
||||
println!("get_photos SQL 语句准备成功");
|
||||
|
||||
let photo_iter = stmt.query_map([model_id], |row| self.row_to_photo(row))?;
|
||||
|
||||
|
|
@ -732,7 +719,6 @@ impl ModelRepository {
|
|||
println!("row_to_photo photo_type 解析失败: {}", e);
|
||||
rusqlite::Error::FromSqlConversionFailure(0, rusqlite::types::Type::Text, Box::new(e))
|
||||
})?;
|
||||
println!("row_to_photo photo_type 解析成功");
|
||||
|
||||
let tags_str: String = row.get("tags")?;
|
||||
let tags: Vec<String> = serde_json::from_str(&tags_str).map_err(|e| {
|
||||
|
|
|
|||
|
|
@ -23,103 +23,8 @@ impl OutfitImageRepository {
|
|||
|
||||
/// 初始化数据库表(强制使用连接池)
|
||||
pub fn init_tables(&self) -> Result<()> {
|
||||
|
||||
// 🚨 强制使用连接池,避免死锁
|
||||
if !self.database.has_pool() {
|
||||
return Err(anyhow!("连接池未启用,无法安全执行数据库操作"));
|
||||
}
|
||||
|
||||
let pooled_conn = self.database.acquire_from_pool()
|
||||
.map_err(|e| anyhow!("获取连接池连接失败: {}", e))?;
|
||||
|
||||
// 创建穿搭图片生成记录表
|
||||
pooled_conn.execute(
|
||||
r#"
|
||||
CREATE TABLE IF NOT EXISTS outfit_image_records (
|
||||
id TEXT PRIMARY KEY,
|
||||
model_id TEXT NOT NULL,
|
||||
model_image_id TEXT NOT NULL,
|
||||
generation_prompt TEXT,
|
||||
status TEXT NOT NULL DEFAULT 'pending',
|
||||
progress REAL NOT NULL DEFAULT 0.0,
|
||||
result_urls TEXT NOT NULL DEFAULT '[]',
|
||||
error_message TEXT,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
started_at DATETIME,
|
||||
completed_at DATETIME,
|
||||
duration_ms INTEGER,
|
||||
comfyui_prompt_id TEXT,
|
||||
FOREIGN KEY (model_id) REFERENCES models (id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (model_image_id) REFERENCES model_photos (id) ON DELETE CASCADE
|
||||
)
|
||||
"#,
|
||||
[],
|
||||
).map_err(|e| anyhow!("创建穿搭图片记录表失败: {}", e))?;
|
||||
|
||||
// 创建商品图片表
|
||||
pooled_conn.execute(
|
||||
r#"
|
||||
CREATE TABLE IF NOT EXISTS product_images (
|
||||
id TEXT PRIMARY KEY,
|
||||
outfit_record_id TEXT NOT NULL,
|
||||
file_path TEXT NOT NULL,
|
||||
file_name TEXT NOT NULL,
|
||||
file_size INTEGER NOT NULL,
|
||||
upload_url TEXT,
|
||||
description TEXT,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (outfit_record_id) REFERENCES outfit_image_records (id) ON DELETE CASCADE
|
||||
)
|
||||
"#,
|
||||
[],
|
||||
).map_err(|e| anyhow!("创建商品图片表失败: {}", e))?;
|
||||
|
||||
// 创建穿搭图片表
|
||||
pooled_conn.execute(
|
||||
r#"
|
||||
CREATE TABLE IF NOT EXISTS outfit_images (
|
||||
id TEXT PRIMARY KEY,
|
||||
outfit_record_id TEXT NOT NULL,
|
||||
image_url TEXT NOT NULL,
|
||||
local_path TEXT,
|
||||
image_index INTEGER NOT NULL,
|
||||
description TEXT,
|
||||
tags TEXT,
|
||||
is_favorite BOOLEAN DEFAULT 0,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (outfit_record_id) REFERENCES outfit_image_records (id) ON DELETE CASCADE
|
||||
)
|
||||
"#,
|
||||
[],
|
||||
).map_err(|e| anyhow!("创建穿搭图片表失败: {}", e))?;
|
||||
|
||||
// 创建索引
|
||||
pooled_conn.execute(
|
||||
"CREATE INDEX IF NOT EXISTS idx_outfit_image_records_model_id ON outfit_image_records (model_id)",
|
||||
[],
|
||||
).map_err(|e| anyhow!("创建索引失败: {}", e))?;
|
||||
|
||||
|
||||
pooled_conn.execute(
|
||||
"CREATE INDEX IF NOT EXISTS idx_outfit_image_records_status ON outfit_image_records (status)",
|
||||
[],
|
||||
).map_err(|e| anyhow!("创建索引失败: {}", e))?;
|
||||
|
||||
pooled_conn.execute(
|
||||
"CREATE INDEX IF NOT EXISTS idx_outfit_image_records_comfyui_prompt_id ON outfit_image_records (comfyui_prompt_id)",
|
||||
[],
|
||||
).map_err(|e| anyhow!("创建索引失败: {}", e))?;
|
||||
|
||||
pooled_conn.execute(
|
||||
"CREATE INDEX IF NOT EXISTS idx_product_images_outfit_record_id ON product_images (outfit_record_id)",
|
||||
[],
|
||||
).map_err(|e| anyhow!("创建索引失败: {}", e))?;
|
||||
|
||||
pooled_conn.execute(
|
||||
"CREATE INDEX IF NOT EXISTS idx_outfit_images_outfit_record_id ON outfit_images (outfit_record_id)",
|
||||
[],
|
||||
).map_err(|e| anyhow!("创建索引失败: {}", e))?;
|
||||
|
||||
// 表创建和索引创建现在通过迁移系统处理
|
||||
// 这个方法保留用于未来可能的初始化逻辑
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -295,7 +295,6 @@ impl Database {
|
|||
// 首先尝试专用只读连接
|
||||
match self.read_connection.try_lock() {
|
||||
Ok(conn) => {
|
||||
println!("使用专用只读连接");
|
||||
return Ok(ConnectionHandle::Single(conn));
|
||||
},
|
||||
Err(_) => {
|
||||
|
|
|
|||
|
|
@ -70,7 +70,6 @@ pub async fn get_all_models(
|
|||
"模特仓库未初始化".to_string()
|
||||
})?;
|
||||
|
||||
println!("调用 ModelService::get_all_models...");
|
||||
let result = ModelService::get_all_models(repository)
|
||||
.map_err(|e| {
|
||||
println!("ModelService::get_all_models 失败: {}", e);
|
||||
|
|
|
|||
|
|
@ -46,7 +46,6 @@ const ModelList: React.FC<ModelListProps> = ({ onModelSelect }) => {
|
|||
try {
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
console.log('开始加载模特列表...');
|
||||
const modelList = await modelService.getAllModels();
|
||||
console.log('模特列表加载成功:', modelList);
|
||||
setModels(modelList);
|
||||
|
|
|
|||
Loading…
Reference in New Issue