9.8 KiB
9.8 KiB
用户导入班级验证优化说明
🎯 需求说明
用户要求
- ❌ 不要在导入前就报错中断
- ✅ 优先完成导入任务
- ✅ 遇到班级不存在的记录,跳过该条记录
- ✅ 继续导入其他记录
- ✅ 最后在导入结果中统一显示失败的记录和原因
✅ 实现方案
方案:逐条验证 + 异常捕获
核心逻辑
- 在处理每个用户时,在插入用户之前验证班级是否存在
- 如果班级不存在,抛出异常
- 外层catch捕获异常,记录到失败信息中
- 继续处理下一个用户
- 最后统一显示导入结果
为什么在插入前验证?
- ✅ 避免用户已插入但班级分配失败
- ✅ 保证数据一致性
- ✅ 失败的用户不会被导入到系统
🔧 修改内容
修改1:移除Controller中的预验证
文件: StudyClassUserController.java
移除的代码:
// 预先验证所有班级是否存在
Set<String> uniqueClassNames = new HashSet<>();
// ... 收集班级名称
Map<String, Long> existingClasses = classUserService.getClassNameToIdMap();
// ... 检查班级
if (!missingClasses.isEmpty())
{
throw new ServiceException("导入失败:...");
}
原因: 不要在导入前就中断整个流程
修改2:添加逐条验证逻辑
文件: StudyClassUserServiceImpl.java
添加的代码:
// 预先验证班级是否存在(在插入/更新用户之前)
if (StringUtils.isNotEmpty(user.getRemark()))
{
String remark = user.getRemark();
int idx = remark.indexOf("班级名称:");
if (idx >= 0)
{
String className = remark.substring(idx + 5).trim();
if (StringUtils.isNotEmpty(className))
{
Long classId = classNameToIdMap.get(className);
if (classId == null)
{
// 班级不存在,抛出异常
throw new ServiceException("信息编号[" + infoNoStr + "]:班级 [" + className + "] 不存在,请先创建该班级");
}
}
}
}
// 验证通过后,再插入/更新用户
SysUser u = userMapper.selectUserById(infoNo);
if (StringUtils.isNull(u))
{
// 插入用户
userMapper.insertUser(user);
// ... 分配班级
}
关键点:
- ✅ 验证在插入用户之前
- ✅ 如果班级不存在,用户不会被插入
- ✅ 异常会被外层catch捕获
修改3:优化异常处理
文件: StudyClassUserServiceImpl.java
班级分配失败时的异常:
else
{
// 班级不存在,抛出异常
throw new ServiceException("班级 [" + className + "] 不存在,请先创建该班级");
}
作用: 作为双重保险,防止遗漏
🔄 完整流程
导入流程图
开始导入
↓
解析Excel(100条记录)
↓
开始逐条处理
↓
┌─────────────────────┐
│ 处理第1条:张三 │
│ 班级:一班 │
│ ↓ │
│ 验证班级是否存在 │
│ ✅ 一班存在 │
│ ↓ │
│ 插入用户 │
│ ↓ │
│ 分配班级 │
│ ↓ │
│ ✅ 导入成功 │
└─────────────────────┘
↓
┌─────────────────────┐
│ 处理第2条:李四 │
│ 班级:三班 │
│ ↓ │
│ 验证班级是否存在 │
│ ❌ 三班不存在 │
│ ↓ │
│ 抛出异常 │
│ ↓ │
│ catch捕获异常 │
│ ↓ │
│ 记录到errorMsg: │
│ "班级[三班]不存在" │
│ ↓ │
│ ❌ 导入失败 │
│ ❌ 用户未插入 │
└─────────────────────┘
↓
┌─────────────────────┐
│ 处理第3条:王五 │
│ 班级:二班 │
│ ↓ │
│ 验证班级是否存在 │
│ ✅ 二班存在 │
│ ↓ │
│ 插入用户 │
│ ↓ │
│ 分配班级 │
│ ↓ │
│ ✅ 导入成功 │
└─────────────────────┘
↓
... 继续处理其他记录 ...
↓
所有记录处理完成
↓
生成导入结果:
- 成功:2条
- 失败:1条
- 失败详情:
1、信息编号 1002,罪犯姓名 李四
失败原因:班级 [三班] 不存在,请先创建该班级
📊 导入结果示例
示例1:部分失败
Excel数据:
信息编号 | 姓名 | 监区 | 班级
1001 | 张三 | A区 | 一班
1002 | 李四 | B区 | 三班
1003 | 王五 | C区 | 二班
1004 | 赵六 | D区 | 四班
数据库班级: 一班、二班(没有三班、四班)
导入结果:
导入完成!
新增: 2 条
更新: 0 条
失败: 2 条
失败详情:
1、信息编号 1002,罪犯姓名 李四
失败原因:信息编号[1002]:班级 [三班] 不存在,请先创建该班级
2、信息编号 1004,罪犯姓名 赵六
失败原因:信息编号[1004]:班级 [四班] 不存在,请先创建该班级
数据库结果:
- ✅ 张三导入成功,分配到一班
- ❌ 李四导入失败,未插入数据库
- ✅ 王五导入成功,分配到二班
- ❌ 赵六导入失败,未插入数据库
示例2:全部成功
Excel数据:
信息编号 | 姓名 | 监区 | 班级
1001 | 张三 | A区 | 一班
1002 | 李四 | B区 | 二班
数据库班级: 一班、二班
导入结果:
导入完成!
新增: 2 条
更新: 0 条
失败: 0 条
示例3:部分无班级
Excel数据:
信息编号 | 姓名 | 监区 | 班级
1001 | 张三 | A区 | 一班
1002 | 李四 | B区 | (空)
1003 | 王五 | C区 | 三班
数据库班级: 一班、二班(没有三班)
导入结果:
导入完成!
新增: 2 条
更新: 0 条
失败: 1 条
失败详情:
1、信息编号 1003,罪犯姓名 王五
失败原因:信息编号[1003]:班级 [三班] 不存在,请先创建该班级
数据库结果:
- ✅ 张三导入成功,分配到一班
- ✅ 李四导入成功,不分配班级(班级为空不验证)
- ❌ 王五导入失败,未插入数据库
⚠️ 重要说明
1. 验证时机
- ✅ 在插入/更新用户之前验证班级
- ✅ 验证失败时,用户不会被插入/更新
- ✅ 保证数据一致性
2. 空班级处理
- ✅ 班级为空时,不进行验证
- ✅ 用户可以导入成功,只是不分配班级
3. 异常处理
- ✅ 每条记录的异常独立处理
- ✅ 一条记录失败不影响其他记录
- ✅ 所有失败记录统一显示
4. 错误信息格式
信息编号[1002]:班级 [三班] 不存在,请先创建该班级
包含信息:
- 信息编号:方便定位是哪条记录
- 班级名称:明确哪个班级不存在
- 操作建议:提示用户先创建班级
🧪 测试场景
测试1:混合场景
Excel:
- 张三 → 一班(存在)
- 李四 → 三班(不存在)
- 王五 → 二班(存在)
- 赵六 → 四班(不存在)
- 孙七 → (空)
预期结果:
✅ 张三导入成功
❌ 李四导入失败(班级不存在)
✅ 王五导入成功
❌ 赵六导入失败(班级不存在)
✅ 孙七导入成功(无班级)
统计:
- 成功:3条
- 失败:2条
- 失败详情列出李四和赵六
🚀 部署步骤
1. 重新编译后端
cd C:\Users\Administrator\Desktop\Project\ry_study-v_03\Study-Vue-redis
mvn clean package -DskipTests
2. 重启后端服务
3. 测试导入
- 创建"一班"和"二班"
- 准备Excel,包含一班、二班、三班
- 执行导入
- 查看导入结果:
- ✅ 一班和二班的用户导入成功
- ❌ 三班的用户导入失败,显示错误信息
📋 验收标准
功能验收
- 班级存在时,用户导入成功
- 班级不存在时,该用户导入失败
- 失败的用户不会被插入到数据库
- 一个用户失败不影响其他用户
- 导入结果显示成功数和失败数
- 失败详情包含信息编号、姓名和失败原因
- 班级为空时,用户可以导入成功
数据一致性验收
- 失败的用户在sys_user表中不存在
- 失败的用户在student_class表中不存在
- 成功的用户正确分配到指定班级
- 没有"用户存在但班级未分配"的情况
用户体验验收
- 导入过程不中断
- 导入结果一次性展示
- 错误信息清晰明确
- 可以根据错误信息快速定位问题
💡 优化建议
建议1:批量创建班级
在导入结果中提供"创建缺失的班级"按钮,一键创建所有不存在的班级
建议2:Excel模板
提供Excel模板下载,包含当前系统中所有班级的下拉列表
建议3:导入预检
在上传Excel后、开始导入前,先显示预检结果(哪些班级不存在)
✅ 总结
优化效果
- ✅ 导入不会因个别记录失败而中断
- ✅ 成功的记录正常导入,失败的记录清晰展示
- ✅ 数据一致性得到保证
- ✅ 用户体验更友好
技术要点
- 逐条验证而非批量验证
- 验证在插入之前而非之后
- 异常独立处理而非全局处理
- 结果统一展示而非即时报错