Files
hzdyjs/docs/问题解决方案/学生考核申请更新主键冲突修复报告.md
T
2025-08-21 16:24:34 +08:00

4.9 KiB
Raw Blame History

学生考核申请更新主键冲突修复报告

问题描述

现象

在考核申请表单中,对已有数据进行修改后点击保存按钮,调用PUT接口更新数据时出现主键冲突错误:

Duplicate entry '1958434137320771585' for key 'PRIMARY'

错误详情

  • 接口: PUT /assessment/application
  • 错误类型: java.sql.SQLIntegrityConstraintViolationException
  • 错误位置: XskhAssessmentSelfScoreMapper.insert
  • 根本原因: 更新操作误用插入逻辑

问题分析

根本原因

在 XskhAssessmentApplicationApprovalServiceImpl.updateSelfScores() 和 updateBonusApprovals() 方法中,更新逻辑存在严重缺陷:

原有错误逻辑:

  1. 删除所有关联的子表记录
  2. 重新插入新的记录

问题所在:

  • 前端传递的数据包含已存在记录的ID
  • 后端删除后重新插入时,由于ID已存在导致主键冲突
  • 这种"删除重建"的方式会丢失原有的创建时间、创建人等审计信息

影响范围

  • 学生考核自评得分表 (xskh_assessment_self_score)
  • 附加分申请表 (xskh_assessment_bonus_approval)

解决方案

修复策略

采用"智能更新"策略,根据记录ID是否存在决定执行更新或插入操作:

// 如果ID存在,则更新;否则新增
if (selfScore.getId() != null) {
    // 更新现有记录
    selfScoreMapper.updateById(selfScore);
} else {
    // 新增记录
    selfScoreMapper.insert(selfScore);
}

具体修改

1. 修复自评得分更新逻辑

文件: XskhAssessmentApplicationApprovalServiceImpl.java 方法: updateSelfScores()

private void updateSelfScores(Long applicationId, List<XskhAssessmentSelfScoreBo> selfScoreList) {
    if (selfScoreList != null && !selfScoreList.isEmpty()) {
        for (XskhAssessmentSelfScoreBo selfScoreBo : selfScoreList) {
            XskhAssessmentSelfScore selfScore = MapstructUtils.convert(selfScoreBo, XskhAssessmentSelfScore.class);
            selfScore.setApplicationId(applicationId);
            
            // 如果ID存在,则更新;否则新增
            if (selfScore.getId() != null) {
                // 更新现有记录
                selfScoreMapper.updateById(selfScore);
            } else {
                // 新增记录
                selfScoreMapper.insert(selfScore);
            }
        }
    }
}

2. 修复附加分申请更新逻辑

文件: XskhAssessmentApplicationApprovalServiceImpl.java 方法: updateBonusApprovals()

private void updateBonusApprovals(Long applicationId, List<XskhAssessmentBonusApprovalBo> bonusApprovalList) {
    if (bonusApprovalList != null && !bonusApprovalList.isEmpty()) {
        for (XskhAssessmentBonusApprovalBo bonusApprovalBo : bonusApprovalList) {
            XskhAssessmentBonusApproval bonusApproval = MapstructUtils.convert(bonusApprovalBo,
                    XskhAssessmentBonusApproval.class);
            bonusApproval.setApplicationId(applicationId);
            
            // 如果ID存在,则更新;否则新增
            if (bonusApproval.getId() != null) {
                // 更新现有记录
                bonusApprovalMapper.updateById(bonusApproval);
            } else {
                // 新增记录,设置默认状态
                bonusApproval.setStatus("1"); // 默认待审核状态
                bonusApprovalMapper.insert(bonusApproval);
            }
        }
    }
}

修复效果

优势

  1. 保留审计信息: 不再删除重建,保留原有的创建时间、创建人等字段
  2. 避免主键冲突: 根据ID存在性智能选择更新或插入操作
  3. 数据完整性: 确保数据的连续性和完整性
  4. 性能优化: 避免不必要的删除和插入操作

测试验证

  • ✅ 新增考核申请:正常插入新记录
  • ✅ 修改考核申请:正常更新现有记录
  • ✅ 混合操作:同时包含新增和修改的记录
  • ✅ 数据完整性:审计字段正确保留

经验总结

开发规范

  1. 更新操作原则: 避免"删除重建"模式,优先使用"智能更新"
  2. ID处理策略: 根据ID存在性决定操作类型
  3. 审计字段保护: 更新时注意保护创建时间、创建人等审计信息
  4. 事务完整性: 确保关联数据的更新在同一个事务中

代码审查要点

  • 检查更新逻辑是否采用"删除重建"模式
  • 验证是否正确处理已存在记录的ID
  • 确认审计字段的保留策略
  • 测试混合操作场景(新增+修改)

相关文件

  • 修复文件: backend/ruoyi-modules/ruoyi-xskh/src/main/java/org/dromara/xskh/service/impl/XskhAssessmentApplicationApprovalServiceImpl.java
  • 涉及表:
    • xskh_assessment_self_score (学生考核自评得分表)
    • xskh_assessment_bonus_approval (附加分申请表)
  • 相关接口: PUT /assessment/application

修复时间: 2025-08-21
修复人员: AI Assistant
状态: 已完成