发现核心问题: - 考试(Exam)和试卷(Paper)共用同一数据对象 - et_exam_exampaper_and_editexampaper 视图合并了两个独立概念 - 字段混用:时间属性和试题属性在同一表 - 无法支持'同一试卷用于多次考试'的业务场景 输出文件:EXAM_PAPER_MODEL_ANALYSIS.md
9.6 KiB
9.6 KiB
考试与试卷数据模型问题分析报告
一、问题概述
当前系统中,考试(Exam) 和 试卷(Paper) 被设计为同一个数据对象,导致两个本应独立的概念混在一起,造成功能边界模糊和数据冗余。
二、当前数据模型分析
2.1 现有数据库表结构
et_exam_examination -- 考试信息表(独立)
├── id -- 考试ID
├── planid -- 关联培训计划ID
├── name -- 考试名称
├── starttime/endtime -- 考试时间窗口
├── duration -- 考试时长
├── isonline -- 是否在线
└── shouldJoin/realJoin -- 应考/实考人数
et_exam_exampaper -- 试卷表(有examid字段关联考试)
├── id -- 试卷ID
├── examid -- 关联考试ID(外键)
├── name -- 试卷名称
├── totalpoints -- 总分
├── passpoint -- 及格分数
├── description -- 描述
├── category -- 所属知识点
├── state -- 状态(是否可编辑)
└── sum1~sum4 -- 各题型数量统计
et_exam_question -- 试题题库表
├── id
├── type -- 题型(1单选2多选3判断4问答)
├── subject -- 题目内容
├── answer -- 正确答案
└── optionA~F -- 选项
et_exam_exampaper_question -- 试卷-题目关联表
├── id
├── examid -- 考试ID
├── questionid -- 试题ID
├── score -- 分值
├── isMust -- 是否必答
└── num -- 题目序号
2.2 实际使用的数据源
代码中实际使用的是 et_exam_exampaper_and_editexampaper 视图/联合表,将考试和试卷合并:
-- 在 SQL 映射中大量使用
select * from et_exam_exampaper_and_editexampaper
这个视图/表包含了考试和试卷的所有字段,导致两个概念完全混在一起。
三、核心问题分析
3.1 问题一:考试与试卷概念混淆
| 维度 | 考试(Exam) | 试卷(Paper) |
|---|---|---|
| 本质 | 一次考试活动 | 一份试题集合 |
| 属性 | 时间、人数、时长 | 题目、总分、及格分 |
| 生命周期 | 有开始/结束时间 | 可长期存在、复用 |
| 关联 | 关联培训计划 | 可关联多个考试 |
当前问题:考试和试卷共用同一张表,无法体现"同一份试卷可用于多次考试"的业务场景。
3.2 问题二:字段冗余与混用
在 exampaper_edit.ftl 中,同一个表单同时包含:
<!-- 考试属性 -->
开放时间:startdate / enddate
考试时长:sc (小时)
<!-- 试卷属性 -->
试卷名称:name
试卷描述:description
及格分数:passpoints
试卷类别:category
这导致:
- 一份试卷不能同时用于多场考试(因为考试时间不同)
- 修改考试时间会影响试卷本身
3.3 问题三:题型统计字段冗余
et_exam_exampaper 表中有 sum1~sum4 字段存储各题型数量:
`sum1` int -- 单选题数量
`sum2` int -- 多选题数量
`sum3` int -- 判断题数量
`sum4` int -- 问答题数量
问题:这些统计值应该通过 SQL 动态计算,而不是冗余存储。试题数量变化时需要手动同步更新。
3.4 问题四:关联表使用不一致
从 et_exam_limitation.map.xml 中可以看到:
-- limitation 表使用 exam_id 关联
select * from et_exam_limitation where exam_id = ?
-- usertest 表也使用 exam_id 关联
select * from et_exam_usertest where exam_id = ?
这里的 exam_id 实际存储的是试卷ID(因为 et_exam_exampaper_and_editexampaper 视图本身就是考试+试卷的合并),命名语义混乱。
3.5 问题五:考试和问卷共用一套表
从代码中可以看到,pg 参数区分:
| pg值 | 类型 | 说明 |
|---|---|---|
| 1 | 考试/试卷 | 需要评分 |
| 2 | 调研问卷 | 不评分 |
但底层共用同一套表结构,只是业务逻辑不同。这种设计虽然灵活,但缺乏清晰的边界。
四、业务场景冲突示例
场景1:同一试卷用于多次考试
业务需求:某课程结业考试,3月份和6月份各举办一次,但使用同一份试卷。
当前限制:
方案A:创建两份试卷(内容完全相同,但ID不同)→ 数据冗余
方案B:使用同一试卷修改时间 → 影响历史考试记录
理想设计:
试卷表(不变) ← 考试表(每次考试独立)
场景2:考试延期
当前问题:
- 用户需要修改考试时间,但操作入口在"编辑试卷"
- 修改后影响所有关联记录
理想设计:
- 考试时间在考试表中独立管理
- 试卷表只负责试题内容
五、建议的数据模型重构
5.1 分离考试和试卷表
┌─────────────────────────────────────────────────────────────┐
│ 当前设计(混用) │
├─────────────────────────────────────────────────────────────┤
│ et_exam_exampaper_and_editexampaper │
│ ├── 考试属性(时间、人数) │
│ └── 试卷属性(题目、总分) │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ 建议设计(分离) │
├─────────────────────────────────────────────────────────────┤
│ et_exam_exampaper(试卷表) │
│ ├── id, name, description, category │
│ ├── totalpoints, passpoint │
│ └── creatperson, edittime │
├─────────────────────────────────────────────────────────────┤
│ et_exam_examination(考试表) │
│ ├── id, paper_id(关联试卷) │
│ ├── name, starttime, endtime, duration │
│ ├── shouldJoin, realJoin │
│ └── state, leader │
├─────────────────────────────────────────────────────────────┤
│ et_exam_exampaper_question(关联表) │
│ ├── id, paper_id, question_id │
│ ├── score(每场考试可单独设置分值) │
│ └── num, isMust │
└─────────────────────────────────────────────────────────────┘
5.2 关键改进点
| 改进项 | 当前 | 建议 |
|---|---|---|
| 试卷复用 | 同一试卷不能用于多场考试 | 一份试卷可关联多场考试 |
| 时间独立 | 考试时间绑定试卷 | 考试时间独立管理 |
| 题目分值 | 固定分值 | 每场考试可单独设置 |
| 题型统计 | 冗余字段 sum1~sum4 | 动态 SQL 计算 |
六、重构风险评估
| 风险项 | 等级 | 说明 |
|---|---|---|
| 历史数据迁移 | 高 | 现有数据需要重新整理 |
| 业务逻辑修改 | 高 | 涉及多个控制器和页面 |
| 关联表改动 | 中 | limitation、usertest 等表需同步修改 |
| 测试工作量 | 高 | 需要全面回归测试 |
七、建议执行步骤
- 分析阶段:梳理所有使用
et_exam_exampaper_and_editexampaper的代码 - 设计阶段:完成新的数据模型设计
- 开发阶段:
- 新建考试表相关逻辑
- 保留试卷表
- 修改关联表
- 数据迁移:编写迁移脚本
- 测试验证:全面回归测试
- 上线部署:灰度发布
八、附录:涉及文件清单
SQL 映射文件
et_exam_exampaper_and_editexampaper.map.xmlet_exam_editexampaper.map.xmlet_exam_usertest.map.xmlet_exam_limitation.map.xml
前端模板
exam/exampaper.ftlexam/exampaper_edit.ftlexam/exampaper_list.ftlexam/exampaper_detail.ftlexam/exam.ftlexam/exam_list.ftl
Java 控制器
ExamController.classExampaperController.classExamResultController.classExampaperServiceImpl.classExamServiceImpl.class
报告生成时间:2026-04-16