|
@@ -119,6 +119,13 @@ public class UnifiedKnowledgeBaseService {
|
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
|
log.warn("classpath种子导入失败: {}", e.getMessage());
|
|
log.warn("classpath种子导入失败: {}", e.getMessage());
|
|
|
}
|
|
}
|
|
|
|
|
+ } else if (backfillMissingModules(rows)) {
|
|
|
|
|
+ // DB 非空但缺少部分模块(种子新增模块后旧库未补齐),从种子回填后重读
|
|
|
|
|
+ try {
|
|
|
|
|
+ rows = knowledgeBaseSectionMapper.selectList(null);
|
|
|
|
|
+ } catch (Exception ignore) {
|
|
|
|
|
+ // 回填后重读失败也不影响:至少新增行已落库,下次启动生效
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (rows != null) {
|
|
if (rows != null) {
|
|
@@ -151,6 +158,79 @@ public class UnifiedKnowledgeBaseService {
|
|
|
indicatorIndex.size(), nutrientIndex.size(), diseaseIndex.size());
|
|
indicatorIndex.size(), nutrientIndex.size(), diseaseIndex.size());
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 回填 DB 中缺失的模块(从 classpath 种子读取),用于种子新增模块后旧库自动补齐(幂等)。
|
|
|
|
|
+ * 仅插入缺失键,不触碰已存在的模块。
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param existingRows 当前 DB 中的行
|
|
|
|
|
+ * @return true=有回填(调用方应重读 DB)
|
|
|
|
|
+ */
|
|
|
|
|
+ private boolean backfillMissingModules(List<KnowledgeBaseSection> existingRows) {
|
|
|
|
|
+ if (existingRows == null || existingRows.isEmpty()) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ Set<String> existingKeys = new HashSet<>();
|
|
|
|
|
+ for (KnowledgeBaseSection r : existingRows) {
|
|
|
|
|
+ if (r.getModuleKey() != null) {
|
|
|
|
|
+ existingKeys.add(r.getModuleKey());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ List<String> missing = new ArrayList<>();
|
|
|
|
|
+ for (String key : MODULE_KEYS) {
|
|
|
|
|
+ if (!existingKeys.contains(key)) {
|
|
|
|
|
+ missing.add(key);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if (missing.isEmpty()) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ Map<String, Object> root;
|
|
|
|
|
+ try (InputStream is = getClass().getResourceAsStream(SEED_CLASSPATH)) {
|
|
|
|
|
+ if (is == null) {
|
|
|
|
|
+ log.warn("种子文件不存在,无法回填缺失模块: {}", SEED_CLASSPATH);
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ root = objectMapper.readValue(is, new TypeReference<Map<String, Object>>() {});
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.warn("读取种子文件失败,无法回填缺失模块: {}", e.getMessage());
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ log.info("检测到知识库缺失模块 {} 个,从classpath种子回填: {}", missing.size(), missing);
|
|
|
|
|
+ boolean filled = false;
|
|
|
|
|
+ Date now = new Date();
|
|
|
|
|
+ for (String key : missing) {
|
|
|
|
|
+ Object content = root.get(key);
|
|
|
|
|
+ if (content == null) {
|
|
|
|
|
+ log.warn("种子文件中缺少模块,跳过回填: {}", key);
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ try {
|
|
|
|
|
+ String moduleVersion = null;
|
|
|
|
|
+ if ("元数据".equals(key) && content instanceof Map) {
|
|
|
|
|
+ Object v = ((Map<String, Object>) content).get("版本");
|
|
|
|
|
+ if (v != null) {
|
|
|
|
|
+ moduleVersion = String.valueOf(v);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ KnowledgeBaseSection row = new KnowledgeBaseSection();
|
|
|
|
|
+ row.setModuleKey(key);
|
|
|
|
|
+ row.setModuleName(key);
|
|
|
|
|
+ row.setContent(objectMapper.writeValueAsString(content));
|
|
|
|
|
+ row.setVersion(moduleVersion);
|
|
|
|
|
+ row.setCreatedAt(now);
|
|
|
|
|
+ row.setUpdatedAt(now);
|
|
|
|
|
+ knowledgeBaseSectionMapper.insert(row);
|
|
|
|
|
+ filled = true;
|
|
|
|
|
+ log.info("回填缺失模块到DB: {}", key);
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ log.warn("回填模块[{}]失败: {}", key, e.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return filled;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* 从 classpath 种子文件导入全部模块到 DB(幂等,存在则更新)
|
|
* 从 classpath 种子文件导入全部模块到 DB(幂等,存在则更新)
|
|
|
*
|
|
*
|