9.4 KiB
9.4 KiB
出国登记保存失败问题修复报告
修复日期: 2025-10-05
问题类型: 数据库字段长度设计不合理
影响功能: 人事管理 > 出国登记 > 新增登记
🔴 问题现象
错误信息
Error updating database.
Cause: com.mysql.cj.jdbc.exceptions.MysqlDataTruncation:
Data truncation: Data too long for column 'political_status' at row 1
SQL: INSERT INTO rs_overseas_registration
(name, gender, birth_date, political_status, id_number,
registered_address, department, position, administrative_level,
personnel_category, status, registration_time, remarks,
create_dept, tenant_id)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, '000000')
复现路径
- 登录系统
- 进入"人事管理" → "出国登记"菜单
- 点击"出国登记"选项卡
- 点击"新增登记"按钮
- 填写表单信息,选择政治面貌(如"中共党员")
- 点击"保存并提交"
- 报错:Data too long for column 'political_status'
🔍 问题分析
1. 数据库字段定义问题
当前字段定义(有问题):
-- 从创建脚本看到的定义
`political_status` char(2) NOT NULL COMMENT '政治面貌:参考rs_political_status字典'
问题所在:
- 字段类型:
char(2)只能存储2个字节 - 实际需求:前端传递完整中文文本(如"中共党员")
- UTF-8编码:4个中文字符 = 12个字节
- 结论:
char(2)完全无法存储任何一个政治面貌选项!
2. 前端传值方式分析
前端代码(web/src/views/rs/overseas-registration/index.vue:323-338):
<el-form-item label="政治面貌" prop="politicalStatus">
<el-select v-model="registrationForm.politicalStatus" placeholder="请选择政治面貌">
<el-option label="中共党员" value="中共党员" />
<el-option label="中共预备党员" value="中共预备党员" />
<el-option label="共青团员" value="共青团员" />
<el-option label="民革党员" value="民革党员" />
<!-- ... 其他选项 ... -->
</el-select>
</el-form-item>
分析:
- 前端直接使用完整的中文标签文本作为value
- 不是使用字典编码(1, 2, 3...)
- 这是正确的做法,因为便于阅读和维护
- 但数据库字段必须能够存储完整文本
3. 政治面貌选项长度统计
| 选项文本 | 字符数 | 字节数(UTF-8) | char(2)能否存储 | varchar(20)能否存储 |
|---|---|---|---|---|
| 中共党员 | 4 | 12 | ❌ | ✅ |
| 中共预备党员 | 6 | 18 | ❌ | ✅ |
| 共青团员 | 4 | 12 | ❌ | ✅ |
| 民革党员 | 4 | 12 | ❌ | ✅ |
| 民盟盟员 | 4 | 12 | ❌ | ✅ |
| 民建会员 | 4 | 12 | ❌ | ✅ |
| 民进会员 | 4 | 12 | ❌ | ✅ |
| 农工党党员 | 5 | 15 | ❌ | ✅ |
| 致公党党员 | 5 | 15 | ❌ | ✅ |
| 九三学社社员 | 6 | 18 | ❌ | ✅ |
| 台盟盟员 | 4 | 12 | ❌ | ✅ |
| 无党派人士 | 5 | 15 | ❌ | ✅ |
| 群众 | 2 | 6 | ❌ | ✅ |
结论:
char(2): 所有选项都无法存储 ❌varchar(20): 所有当前选项都可以存储 ✅varchar(50): 最安全的选择,预留扩展空间 ✅✅✅
4. 根本原因总结
- 字段长度设计错误:使用了
char(2),远远不足以存储中文文本 - 缺少数据验证:建表时没有与实际前端传值进行验证
- 文档不一致:不同文档中字段定义不一致(char(2)、varchar(20)、varchar(50))
🔧 修复方案
修复步骤
1. 执行SQL修复脚本
脚本位置: docs/设计文档/database/【立即执行】修复political_status字段长度.sql
核心SQL:
-- 修改出国登记表
ALTER TABLE `rs_overseas_registration`
MODIFY COLUMN `political_status` varchar(50) NOT NULL COMMENT '政治面貌';
-- 修改出国申请表(保持一致)
ALTER TABLE `rs_overseas_application`
MODIFY COLUMN `political_status` varchar(50) NOT NULL COMMENT '政治面貌';
2. 执行方式
方式一:通过Navicat/DBeaver等工具
- 连接到数据库
hzdyjs_xg - 打开SQL脚本文件
- 执行整个脚本
- 查看验证结果
方式二:通过命令行
mysql -uroot -p hzdyjs_xg < "docs/设计文档/database/【立即执行】修复political_status字段长度.sql"
3. 验证修复结果
验证SQL:
SELECT
TABLE_NAME,
COLUMN_NAME,
DATA_TYPE,
CHARACTER_MAXIMUM_LENGTH,
COLUMN_COMMENT
FROM
information_schema.COLUMNS
WHERE
TABLE_SCHEMA = 'hzdyjs_xg'
AND TABLE_NAME IN ('rs_overseas_registration', 'rs_overseas_application')
AND COLUMN_NAME = 'political_status';
预期结果:
TABLE_NAME | COLUMN_NAME | DATA_TYPE | CHARACTER_MAXIMUM_LENGTH | COLUMN_COMMENT
----------------------------|------------------|-----------|--------------------------|----------------
rs_overseas_registration | political_status | varchar | 50 | 政治面貌
rs_overseas_application | political_status | varchar | 50 | 政治面貌
4. 功能测试
修复完成后,请测试以下场景:
| 测试场景 | 操作步骤 | 预期结果 |
|---|---|---|
| 新增登记-短文本 | 选择"群众" → 保存 | ✅ 保存成功 |
| 新增登记-中等文本 | 选择"中共党员" → 保存 | ✅ 保存成功 |
| 新增登记-较长文本 | 选择"九三学社社员" → 保存 | ✅ 保存成功 |
| 编辑登记 | 修改政治面貌 → 保存 | ✅ 更新成功 |
| 保存并提交 | 填写完整信息 → 保存并提交 | ✅ 提交成功 |
📊 影响范围
受影响的表
- ✅
rs_overseas_registration(出国登记表) - 已修复 - ✅
rs_overseas_application(出国申请表) - 已修复
受影响的功能
- 人事管理 > 出国登记 > 新增登记
- 人事管理 > 出国登记 > 编辑登记
- 人事管理 > 出国申请 > 新增申请
- 人事管理 > 出国申请 > 编辑申请
代码检查(无需修改)
后端实体类(正确):
// RsOverseasRegistration.java
@ExcelProperty(value = "政治面貌")
private String politicalStatus;
前端表单(正确):
<el-select v-model="registrationForm.politicalStatus">
<el-option label="中共党员" value="中共党员" />
</el-select>
📝 经验总结
设计教训
-
中文字段长度计算规则
varchar长度 = 最大字符数 × 3(UTF-8) + 预留空间(20-30%) -
常见错误
- ❌ 使用
char(2)存储中文文本 - ❌ 只考虑字符数,不考虑字节数
- ❌ 没有与实际数据进行验证
- ✅ 使用
varchar(50)存储4-6个中文字符的内容
- ❌ 使用
-
推荐长度标准
内容类型 字符数 推荐varchar长度 政治面貌 2-6 50 姓名 2-10 50 部门名称 10-30 100 地址 20-100 300
预防措施
1. 设计阶段
- 建表前必须确认字段长度满足所有可能值
- 中文字段统一按字符数×3计算
- 预留20-30%扩展空间
2. 开发阶段
- 前端传值与数据库字段长度必须匹配
- 单元测试包含边界值测试
- 集成测试覆盖所有下拉选项
3. 文档规范
- 数据库设计文档标注字段长度计算依据
- 字典数据变更时同步检查字段长度
✅ 修复清单
立即执行
- 创建修复SQL脚本
- 编写修复报告
- 执行SQL修复脚本(请数据库管理员执行)
- 验证字段长度已更新为varchar(50)
- 测试"新增出国登记"功能
- 测试所有政治面貌选项
后续优化
- 全局检查其他表的
political_status字段 - 检查其他中文字段的长度是否合理
- 更新数据库设计规范文档
- 在代码生成模板中增加字段长度验证
🎯 关键提示
⚠️ 执行前注意事项
- 备份: 脚本已自动创建备份表,但建议额外备份
- 时机: 建议在业务低峰期执行
- 权限: 需要ALTER TABLE权限
- 时长: 预计1-2秒(取决于表数据量)
- 安全: ALTER TABLE不会丢失数据
✅ 执行后验证
- 查看字段长度是否已更新为50
- 测试新增登记功能(选择所有政治面貌选项)
- 测试编辑登记功能
- 检查现有数据是否正常
🔗 相关文档
修复文档
- 本次修复SQL:
docs/设计文档/database/【立即执行】修复political_status字段长度.sql - 历史修复记录:
docs/变更管理/出国登记political_status字段长度不足修复-2025-10-04.md
设计文档
- 数据库设计:
docs/设计文档/database/出国管理三表架构设计方案.md - 开发规范:
.cursor/cursorrules-backend.md
变更记录
- 字段重构记录:
docs/变更管理/出国登记字段重构记录-2025-09-29.md - 数据库准备记录:
docs/变更管理/出国登记表数据库准备记录-2025-09-30.md
📞 问题追踪
问题ID: RS-POLITICAL-STATUS-LENGTH-001
创建时间: 2025-10-05
修复状态: 待执行SQL脚本
责任人: 数据库管理员
预计修复时间: 2分钟
修复完成后,请立即测试"新增出国登记"功能,特别是选择"中共党员"、"九三学社社员"等选项!