9.9 KiB
9.9 KiB
信贷客户家庭关系导入功能对齐测试报告
修改概述
本次修改将信贷客户家庭关系功能的导入实现完全对齐到员工亲属关系的成熟模式,提升了代码质量、性能和用户体验。
修改日期: 2026-02-11
参考模板: CcdiStaffEnterpriseRelationImportServiceImpl
修改对象: CcdiCustFmyRelationImportServiceImpl
修改文件清单
1. Mapper 层
文件: CcdiCustFmyRelationMapper.java
- ✅ 新增
batchExistsByCombinations方法接口 - ✅ 支持批量查询已存在的关系组合
文件: CcdiCustFmyRelationMapper.xml
- ✅ 实现
batchExistsByCombinationsSQL - ✅ 优化:从 N 次查询减少到 1 次查询
<select id="batchExistsByCombinations" resultType="string">
SELECT CONCAT(person_id, '|', relation_type, '|', relation_cert_no)
FROM ccdi_cust_fmy_relation
WHERE is_cust_family = 1 AND status = 1
AND CONCAT(person_id, '|', relation_type, '|', relation_cert_no) IN
<foreach collection="combinations" item="combo" open="(" separator="," close=")">
#{combo}
</foreach>
</select>
2. Service 层
文件: CcdiCustFmyRelationImportServiceImpl.java
- ✅ 完全重构,参考员工亲属关系实现
- ✅ 引入
ImportLogUtils统一日志记录 - ✅ 实现
getExistingCombinations批量查询 - ✅ 添加 Excel 内部重复检查
- ✅ 优化 Redis 状态管理(Hash 结构)
- ✅ 实现分批插入(每批500条)
- ✅ 添加
getImportStatus方法 - ✅ 优化失败记录存储(JSON 序列化,7天过期)
文件: CcdiCustFmyRelationServiceImpl.java
- ✅ 更新
importRelations方法,传递 userName 参数 - ✅ 初始化 Redis 状态为 Hash 结构
- ✅ 使用
EasyExcelUtil进行导出和模板下载 - ✅ 添加数据量校验
3. Controller 层
文件: CcdiCustFmyRelationController.java
- ✅ 导入接口返回
ImportResultVO对象 - ✅ 状态查询接口返回
ImportStatusVO对象 - ✅ 失败记录接口支持分页
- ✅ 使用
EasyExcelUtil工具类
4. VO 类
- ✅ 复用
ImportStatusVO.java - ✅ 复用
ImportResultVO.java - ✅ 复用
CustFmyRelationImportFailureVO.java
5. Excel 实体
文件: CcdiCustFmyRelationExcel.java
- ✅ 已包含完整的
@DictDropdown注解ccdi_relation_type(关系类型)ccdi_indiv_gender(性别)ccdi_certificate_type(证件类型)
核心改进点
1. 性能优化
| 项目 | 优化前 | 优化后 | 提升 |
|---|---|---|---|
| 唯一性检查 | N 次数据库查询 | 1 次批量查询 | 约 90% |
| 批量插入 | 无分批控制 | 每批 500 条 | 更稳定 |
| 导入1000条 | 预计 30-50秒 | 预计 10-15秒 | 约 60% |
2. Redis 状态管理升级
优化前:
Key: import:custFmyRelation:{taskId}
Value: "COMPLETED:10:5"
TTL: 1 小时
优化后:
Key: import:custFmyRelation:{taskId}
Type: Hash
Fields:
- taskId: "uuid"
- status: "SUCCESS" | "PARTIAL_SUCCESS" | "PROCESSING"
- totalCount: 100
- successCount: 95
- failureCount: 5
- progress: 100
- startTime: 1234567890
- endTime: 1234567900
- message: "成功95条,失败5条"
TTL: 7 天
3. 导入日志记录
使用 ImportLogUtils 统一记录:
- ✅ 导入开始/结束
- ✅ 批量查询日志
- ✅ 进度跟踪
- ✅ 验证错误详情
- ✅ 批量操作日志
- ✅ Redis 操作日志
4. 数据验证增强
- ✅ 身份证号格式验证(18位)
- ✅ 字段长度验证
- ✅ Excel 内部重复检查
- ✅ 数据库唯一性检查(批量)
测试指南
测试环境准备
- 启动后端服务 (
mvn spring-boot:run) - 确保数据库连接正常
- 确保 Redis 服务运行
测试步骤
1. 下载导入模板
POST /ccdi/custFmyRelation/importTemplate
Headers:
Authorization: Bearer {token}
预期结果:
- 返回 Excel 文件
- 包含字典下拉框(关系类型、性别、证件类型)
2. 准备测试数据
创建包含以下字段的测试数据:
| 信贷客户身份证号 | 关系类型 | 关系人姓名 | 性别 | 关系人证件类型 | 关系人证件号码 |
|---|---|---|---|---|---|
| 110101199001011234 | 配偶 | 张三 | 男 | 身份证 | 110101199001011235 |
| 110101199001011234 | 子女 | 李四 | 女 | 身份证 | 110101201001011236 |
测试场景:
- ✅ 正常数据导入
- ✅ 重复数据导入(应返回错误)
- ✅ Excel 内部重复(应检测并报错)
- ✅ 必填字段缺失(应返回详细错误)
3. 提交导入任务
POST /ccdi/custFmyRelation/importData
Headers:
Authorization: Bearer {token}
Form Data:
file: 测试数据.xlsx
预期响应:
{
"code": 200,
"msg": "导入任务已提交,正在后台处理",
"data": {
"taskId": "uuid-string",
"status": "PROCESSING",
"message": "导入任务已提交,正在后台处理"
}
}
4. 查询导入状态
GET /ccdi/custFmyRelation/importStatus/{taskId}
Headers:
Authorization: Bearer {token}
预期响应:
{
"taskId": "uuid-string",
"status": "SUCCESS",
"totalCount": 2,
"successCount": 2,
"failureCount": 0,
"progress": 100,
"message": "全部成功!共导入2条数据"
}
5. 查询失败记录
GET /ccdi/custFmyRelation/importFailures/{taskId}?pageNum=1&pageSize=10
Headers:
Authorization: Bearer {token}
预期响应 (如果有失败):
{
"total": 1,
"rows": [
{
"rowNum": 2,
"personId": "110101199001011234",
"relationType": "配偶",
"relationName": "张三",
"errorMessage": "该关系已存在,请勿重复导入"
}
],
"code": 200,
"msg": "查询成功"
}
自动化测试脚本
使用提供的测试脚本:
doc\test-scripts\test-cust-fmy-relation-import.bat
测试脚本功能:
- 登录获取 token
- 下载导入模板
- 提交导入任务
- 查询导入状态
- 查询失败记录
- 测试查询接口
验证清单
功能验证
- 导入模板下载正常
- 导入任务提交成功
- 导入状态查询正常
- 导入成功数据正确插入数据库
- 重复数据被正确拦截
- Excel 内部重复被检测
- 失败记录正确保存到 Redis
- 失败记录查询支持分页
- 导入日志正常输出
性能验证
- 导入 100 条数据 < 5 秒
- 导入 1000 条数据 < 20 秒
- 批量查询只执行 1 次 SQL
- Redis 状态更新及时
日志验证
- 导入开始日志
- 批量查询日志
- 进度日志
- 验证错误日志
- 批量操作日志
- 导入完成日志
API 文档更新
导入相关接口
1. 下载导入模板
POST /ccdi/custFmyRelation/importTemplate
Authorization: Bearer {token}
Content-Type: application/json
Response: Excel 文件
2. 提交导入任务
POST /ccdi/custFmyRelation/importData
Authorization: Bearer {token}
Content-Type: multipart/form-data
Form Data:
file: Excel 文件
Response:
{
"code": 200,
"msg": "导入任务已提交,正在后台处理",
"data": {
"taskId": "uuid",
"status": "PROCESSING",
"message": "导入任务已提交,正在后台处理"
}
}
3. 查询导入状态
GET /ccdi/custFmyRelation/importStatus/{taskId}
Authorization: Bearer {token}
Response:
{
"code": 200,
"data": {
"taskId": "uuid",
"status": "SUCCESS",
"totalCount": 100,
"successCount": 95,
"failureCount": 5,
"progress": 100,
"startTime": 1234567890,
"endTime": 1234567900,
"message": "成功95条,失败5条"
}
}
4. 查询导入失败记录
GET /ccdi/custFmyRelation/importFailures/{taskId}?pageNum=1&pageSize=10
Authorization: Bearer {token}
Response:
{
"code": 200,
"total": 5,
"rows": [...],
"msg": "查询成功"
}
回归测试建议
测试场景
- 正常数据导入: 全部字段完整有效
- 必填字段缺失: 缺少 personId、relationType 等
- 格式错误: 身份证号格式不正确
- 数据重复:
- 数据库中已存在
- Excel 文件内重复
- 大数据量: 导入 1000+ 条数据
- 并发导入: 同时提交多个导入任务
- 边界情况: 空文件、单条数据、最大字段长度
性能基准
| 数据量 | 预期时间 | 最大内存 |
|---|---|---|
| 10 条 | < 2 秒 | < 50MB |
| 100 条 | < 5 秒 | < 100MB |
| 1000 条 | < 20 秒 | < 200MB |
| 10000 条 | < 3 分钟 | < 500MB |
注意事项
1. 字典配置
确保以下字典数据已配置:
ccdi_relation_type(关系类型)ccdi_indiv_gender(性别)ccdi_certificate_type(证件类型)
2. Redis 配置
- 确保 Redis 服务运行
- 检查 Redis 过期策略
- 监控 Redis 内存使用
3. 异步配置
- 确保
@EnableAsync已启用 - 检查异步线程池配置
- 监控异步任务执行情况
4. 日志级别
- 生产环境: INFO
- 开发环境: DEBUG
- 测试环境: DEBUG
后续优化建议
1. 导入进度实时推送
考虑使用 WebSocket 实现导入进度实时推送,替代轮询查询。
2. 导入历史记录
添加导入历史记录表,记录每次导入的详细信息,便于追溯。
3. 数据预校验
在前端添加数据预校验,提前发现格式错误,减少无效提交。
4. 导入模板智能生成
根据数据库字典动态生成导入模板,减少维护成本。
5. 批量操作优化
考虑使用 MyBatis Plus 的 SqlInjector 实现真正的批量插入。
创建日期
2026-02-11