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

144 lines
4.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 学生考核申请更新主键冲突修复报告
## 问题描述
### 现象
在考核申请表单中,对已有数据进行修改后点击保存按钮,调用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是否存在决定执行更新或插入操作:
```java
// 如果ID存在,则更新;否则新增
if (selfScore.getId() != null) {
// 更新现有记录
selfScoreMapper.updateById(selfScore);
} else {
// 新增记录
selfScoreMapper.insert(selfScore);
}
```
### 具体修改
#### 1. 修复自评得分更新逻辑
**文件**: `XskhAssessmentApplicationApprovalServiceImpl.java`
**方法**: `updateSelfScores()`
```java
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()`
```java
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
**状态**: 已完成