From db292ff4d00c38d44cc5ea45a36b81a3834f241d Mon Sep 17 00:00:00 2001 From: wanghanlin <1533525126@qq.com> Date: Thu, 2 Jul 2026 14:38:27 +0800 Subject: [PATCH] =?UTF-8?q?fix(=E7=9F=A5=E8=AF=86=E5=BA=93):=20=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E6=96=87=E6=A1=A3=E5=88=86=E5=9D=97=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?=E5=92=8C=E5=88=87=E6=8D=A2=E7=8A=B6=E6=80=81=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修复 vector_store 表缺少 create_time 列导致分块查询失败 - 添加幂等迁移方法,自动为 vector_store 表添加 create_time 列 - 兼容 Spring AI 自动建表时不含此列的情况 - 修复切换文档启用/禁用状态失败 - 解决 PostgreSQL json/jsonb 类型不匹配问题 - 使用 metadata::jsonb 显式类型转换 - 统一 enabled 值写入为字符串类型,与搜索过滤条件一致 - 修复批量启用/禁用文档功能 - 同步修复 batchToggleDocuments 方法的相同问题 影响范围: - 文档分块查看/编辑/删除功能恢复正常 - 文档启用/禁用功能恢复正常 - 批量操作功能恢复正常 测试验证: - 文档分块查询:✅ 通过 - 切换文档状态:✅ 通过 - 批量启用文档:✅ 通过 - 全量回归测试:✅ 无新增问题 --- .../supportbot/config/DatabaseInitConfig.java | 36 ++++++++++++++++++- .../supportbot/service/DocumentService.java | 10 +++--- 2 files changed, 41 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/wok/supportbot/config/DatabaseInitConfig.java b/src/main/java/com/wok/supportbot/config/DatabaseInitConfig.java index cdfa8fe..67e832e 100644 --- a/src/main/java/com/wok/supportbot/config/DatabaseInitConfig.java +++ b/src/main/java/com/wok/supportbot/config/DatabaseInitConfig.java @@ -10,7 +10,11 @@ import org.springframework.stereotype.Component; /** * 数据库初始化配置 - * 应用启动时检查并创建必要的表 + * 应用启动时检查并创建必要的表、迁移列、同步种子数据。 + * + * ⚠️ 开发规范:任何涉及建表、增删改列、初始数据的变更, + * 必须同时更新本类(init 方法)和 init-database.sql(手动备用脚本), + * 保持两者一致,否则新部署环境会丢失变更。 */ @Component @Slf4j @@ -181,6 +185,9 @@ public class DatabaseInitConfig { // P0-001: 混合检索 - 为 vector_store 添加全文检索列 safeInit("初始化 vector_store 全文检索", this::initVectorStoreFullTextSearch); + // 迁移 vector_store.create_time 列(Spring AI 自动建表时不包含此列) + safeInit("迁移 vector_store.create_time 列", this::addVectorStoreCreateTimeColumn); + // 为所有表添加注释(幂等,可重复执行) safeInit("应用数据库表注释", this::applyTableComments); @@ -754,6 +761,33 @@ public class DatabaseInitConfig { } } + /** + * 为 vector_store 表添加 create_time 列。 + * Spring AI 自动建表时不会创建此列,但 DocumentService 查询分块列表时需要按 create_time 排序。 + * 幂等:已有列则跳过。 + */ + private void addVectorStoreCreateTimeColumn() { + try { + // 表不存在时直接跳过,等待 Spring AI 创建后再迁移 + if (!checkTableExists("vector_store")) { + log.debug("vector_store 表尚未创建,跳过 create_time 列迁移"); + return; + } + + String checkSql = "SELECT COUNT(*) FROM information_schema.columns WHERE table_name = 'vector_store' AND column_name = 'create_time'"; + Integer count = jdbcTemplate.queryForObject(checkSql, Integer.class); + if (count != null && count == 0) { + log.info("添加 vector_store.create_time 列"); + jdbcTemplate.execute("ALTER TABLE vector_store ADD COLUMN create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL"); + // 为已有记录回填创建时间(使用当前时间作为兜底) + jdbcTemplate.execute("UPDATE vector_store SET create_time = CURRENT_TIMESTAMP WHERE create_time IS NULL"); + log.info("vector_store.create_time 列添加完成"); + } + } catch (Exception e) { + log.error("添加 vector_store.create_time 列失败,请手动执行: ALTER TABLE vector_store ADD COLUMN create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL", e); + } + } + // ==================== P1-001: 用户认证与多用户管理 ==================== private void createSysUserTable() { diff --git a/src/main/java/com/wok/supportbot/service/DocumentService.java b/src/main/java/com/wok/supportbot/service/DocumentService.java index 7ceba21..74b555e 100644 --- a/src/main/java/com/wok/supportbot/service/DocumentService.java +++ b/src/main/java/com/wok/supportbot/service/DocumentService.java @@ -551,12 +551,14 @@ public class DocumentService { /** * 同步更新 vector_store 中指定文档所有分块的 enabled metadata - * 使用 JdbcTemplate 直接 UPDATE JSONB 字段 + * 使用 JdbcTemplate 直接 UPDATE JSON 字段 + * 注意:Spring AI 的 PgVectorStore 自动建表时 metadata 是 json 类型,不是 jsonb + * 统一写入字符串类型 "true"/"false",与 searchDocuments 的过滤条件保持一致 */ private void syncVectorEnabledMetadata(String documentId, boolean enabled) { - String sql = "UPDATE vector_store SET metadata = jsonb_set(metadata, '{enabled}', ?) " + - "WHERE metadata->>'documentId' = ?"; - // 写入 JSONB 布尔值(true/false),而非字符串 "true"/"false" + // 使用 to_jsonb(?::text) 将字符串转换为 JSONB 字符串值,与 searchDocuments 过滤条件一致 + String sql = "UPDATE vector_store SET metadata = (jsonb_set(metadata::jsonb, '{enabled}', " + + "to_jsonb(?::text)))::json WHERE metadata->>'documentId' = ?"; jdbcTemplate.update(sql, enabled ? "true" : "false", documentId); }