《技术底稿 42》查新功能通用化改造:从单一期刊到多源命中,缓存与表结构一次重构

一、改造背景:为什么要做

旧版查新功能只支持期刊类型,且缓存Key设计有缺陷(临时查新会冲突),数据库字段约束过死(subjectId、projectId必填导致临时查新无法保存)。

业务需要支持成果(achievement)和期刊(periodical)两种命中类型。临时查新(没有subjectId/projectId)需要独立缓存Key,否则会互相覆盖。前端需要统一的文件下载方式,不能直接暴露URL。

二、核心改动:三块一起动

2.1 VO字段重命名(前后端对齐)

改动项 原因
字段名 periodicalNo referenceNo 不再只支持期刊,统一叫"参考文件编号"
新增字段 bizFileId 前端统一用这个字段调下载接口
删除字段 url 安全考虑,不让前端直接调文件URL

2.2 缓存Key优化(解决临时查新冲突)

旧逻辑:可能只用某一个ID,临时查新时ID为空,导致Key重复覆盖

新逻辑:三级优先级,有哪个用哪个

java 复制代码
private String buildCacheId(NoveltyCheckDTO reqDTO) {
    if (reqDTO.getProjectId() != null) return String.valueOf(reqDTO.getProjectId());
    if (reqDTO.getSubjectId() != null) return String.valueOf(reqDTO.getSubjectId());
    return reqDTO.getRequestId();  // 临时查新走这里
}

2.3 数据库表结构调整(放宽约束)

sql 复制代码
ALTER TABLE `kl_novelty_check` 
MODIFY COLUMN `subject_id` bigint NULL COMMENT '查新主体ID(临时查新可为空)',
MODIFY COLUMN `project_id` bigint NULL DEFAULT NULL COMMENT '关联期刊项目ID(临时查新可为空)';

改动原因:临时查新没有subjectId/projectId,强制非空会插入失败。

三、XXXX查新策略完善(核心逻辑)

3.1 支持两种命中类型

source_type 处理方式 查询逻辑
achievement 通过achievement_id → bkl_file 直接获取文件名和fileId
periodical 通过project_id → periodical_document 查询最新版本原始文档

3.2 periodical类型的特殊处理

java 复制代码
List<PeriodicalDocument> documents = periodicalDocumentService.list(
    Wrappers.lambdaQuery(PeriodicalDocument.class)
        .eq(PeriodicalDocument::getProjectId, projectId)
        .eq(PeriodicalDocument::getDocumentType, "origin")
        .orderByDesc(PeriodicalDocument::getVersion)
        .last("limit 1")
);

关键点 :只取document_type = origin的最新版本。

四、修复的问题清单

问题 解决方案
createTime类型不匹配 统一使用LocalDateTime
查新结果不显示期刊号 通过成果ID关联bkl_file
临时查新缓存Key冲突 用requestId作为兜底缓存Key
periodical类型无法关联文件 通过project_id查询periodical_document
文档类型判断混乱 区分type=3(期刊)和origin(原始文档)

五、最终返回结果示例

java 复制代码
{
  "referenceFiles": [
    {
      "id": "0000001",
      "referenceNo": "NO1111111-深度学习的智慧能源管理系统",
      "title": "本发明涉及一种基于深度学习的智慧能源管理系统...",
      "similarity": 80,
      "bizFileId": 1
    }
  ],
  "riskLevel": "LOW",
  "riskTitle": "存在1件高度相似期刊,建议修改调整",
  "aiModificationSuggestion": "⚠️ 一般警示:存在相似期刊..."
}

六、待优化项

  • 数据去重:多个项目重复上传相同文件的问题(业务层面)

  • 文件名显示:过长时可截断

  • 其他查新类型:论文/标准(已预留,暂未实现)

七、涉及的核心文件

文件 改动内容
NoveltyCheckVO.java 字段重命名
NoveltyCheckBizServiceImpl.java 缓存Key优化、临时查新支持
XXXXNoveltyCheckStrategy.java 完整重写,支持两种类型
NoveltyCheckDataServiceImpl.java saveNewVersion支持subjectId为空
kl_novelty_check表 subject_id、project_id改为可空

八、底稿收尾落款

本文为《技术底稿》系列第 42 篇,记录查新功能从单一期刊查新升级为通用查新的完整改造过程。

涉及VO字段重命名、缓存Key优先级重构、数据库约束放宽、多源命中策略落地等多个改动点,是一次典型的功能通用化重构实践。

改造完成后,查新功能已支持achievement和periodical两种命中类型,临时查新场景不再有缓存冲突,前端文件下载统一走bizFileId接口,整体安全性和扩展性都有明显提升。

同类功能通用化改造、多类型命中策略设计,可作为参考范本。

相关推荐
咩咩啃树皮1 小时前
第43篇:Vue3计算属性(computed)完全精讲——缓存机制、依赖计算、业务最优解
前端·vue.js·缓存
小Ti客栈3 小时前
Spring Boot 集成 Springdoc-OpenAPI 与 Knife4j实现接口文档与可视化调试
java·spring boot·后端
Ai拆代码的曹操4 小时前
Spring 事务 REQUIRES_NEW 嵌套调用:连接池翻倍的秘密
java·后端·spring
动恰客流统计4 小时前
ReID边缘计算视觉统计:餐饮店客流增长的数字化破局路径
java·大数据·运维·人工智能
Ivanqhz5 小时前
Rust &‘static str浅析
java·前端·javascript·rust
IT_陈寒5 小时前
SpringBoot这个分页坑,我踩了三天才爬出来
前端·人工智能·后端
颜酱5 小时前
05 | 召回前置准备:根据业务数据库生成各数据库(读取配置阶段)
前端·人工智能·后端
Wang's Blog5 小时前
Go-Zero项目开发24: 基于Bitmap实现群聊消息已读未读
开发语言·后端·golang
Conan在掘金6 小时前
鸿蒙报错速查:struct 里嵌 namespace 声明就炸,根因 + 真解法
后端
东方小月6 小时前
从零开发一个 Coding Agent(三):EventStream 事件流通道设计与实现
前端·人工智能·后端