前言
起初,在开发过程中完成了一个分页查询的接口。当时测试了一下,分页信息和数据也一并返回了,没有仔细看返回的数据,本以为接口已经大功告成了。然而并没有结束…
后来在测试数据增加多的时候,不妙的事情发生了。分页参数中很明显不对的就是总条数和总页数。下面进行事故的分析
背景
数据库:sqlserver
orm:mybatis
分页查询异常表现
bug修复前的代码
- 数据库查询的数据
/**
* 条件分页查询
*
* @param condition 查询条件
* @param currentPage 当前页数
* @param pageSize 每页显示条数
* @return BaseVO<PageInfo < FormData>>
*/
@Override
public BaseVO<PageInfo<FormData>> formDataList(String condition, Integer currentPage, Integer pageSize, InitSource initSource) {
PageHelper.startPage(currentPage, pageSize);
QueryObject queryObject = analysisConditionUtil.queryObject(condition, initSource);
if (Objects.isNull(queryObject)) {
return new BaseVO<>(BaseVO.ILLEGAL_PARAM_CODE, "操作方式有误,仅支持 大于,小于,"
+ "等于,不等于,大于等于,小于等于,在其中,不在其中");
}
List<Map<String, Object>> maps = zhongLvDao.getFormDataList(queryObject);
//将查询到的数据的字段名称替换为中文名称
//【从数据库返回的数据没有直接返回,做了些数据处理,问题就发生在数据处理的时候】
List<FormData> formDataList = structFormDatalist(initSource, maps);
PageInfo<FormData> pageInfo = new PageInfo<>(formDataList);
return new BaseVO<>(BaseVO.SUCCESS_CODE, "查询成功", pageInfo);
}
- 数据处理
/**
* 将查询到的数据的第三方的英文字段替换为中文字段
*
* @param zhongLvSource json中定义的中文字段和第三方英文字段的对应关系
* @param dataList List<Map<英文名称, value>>: 查询到的第三方的数据
* @return List<FormData> 英文字段替换为中文字段的最终数据
*/
private List<FormData> structFormDatalist(InitSource zhongLvSource, List<Map<String, Object>> dataList) {
//1.非常不妙的事情其实就发生在这个地方,datalist本身是一个page对象,里面包含了分页信息
//2.但是经过数据处理后需要返回 List<FormData>的数据结构,就在创建了新的对象的同时并没有将已经存在的分页信息拷贝到新的对象中,导致数据丢失
List<FormData> formDataList = new ArrayList<>();
for (Map<String, Object> stringDataBaseMap : dataList) {
FormData formData = new FormData();
Map<String, DataBase> data = new HashMap<>();
Set<Map.Entry<String, Object>> entries = stringDataBaseMap.entrySet();
for (Map.Entry<String, Object> entry : entries) {
Field fieldByEnName = zhongLvSource.getFieldByEnName(entry.getKey());
if (!Objects.isNull(fieldByEnName)) {
constructCommdata(data, entry, fieldByEnName.getCnName(), fieldByEnName.getType());
} else {
Field fieldByAlias = zhongLvSource.getFieldByAlias(entry.getKey());
if (!Objects.isNull(fieldByAlias)) {
constructCommdata(data, entry, fieldByAlias.getCnName(), fieldByAlias.getType());
}
}
formData.setData(data);
}
formDataList.add(formData);
}
return formDataList;
}
- 问题分析
- 下图为数据库返回的数据进行处理的逻辑,处理完成返回ArrayList类型的数据
- 下图为数据库返回的数据进行处理的逻辑,处理完成返回ArrayList类型的数据
- 将返回的数据通过
- 跟踪进入PageInfo方法,追查赋值过程
修复bug
- bug修复后的查询结果
- 代码改动的地方
/**
* 将查询到的数据的第三方的英文字段替换为中文字段
*
* @param zhongLvSource json中定义的中文字段和第三方英文字段的对应关系
* @param dataList List<Map<英文名称, value>>: 查询到的第三方的数据
* @return List<FormData> 英文字段替换为中文字段的最终数据
*/
private List<FormData> structFormDatalist(InitSource zhongLvSource, List<Map<String, Object>> dataList) {
//拷贝分页信息【在返回的时候需要保持原来的数据结构,得返回一个新的page对象,并且将分页信息拷贝到新的page对象中】
Page<FormData> formDataList = new Page<>();
BeanUtils.copyProperties(dataList, formDataList);
for (Map<String, Object> stringDataBaseMap : dataList) {
FormData formData = new FormData();
Map<String, DataBase> data = new HashMap<>();
Set<Map.Entry<String, Object>> entries = stringDataBaseMap.entrySet();
for (Map.Entry<String, Object> entry : entries) {
Field fieldByEnName = zhongLvSource.getFieldByEnName(entry.getKey());
if (!Objects.isNull(fieldByEnName)) {
constructCommdata(data, entry, fieldByEnName.getCnName(), fieldByEnName.getType());
} else {
Field fieldByAlias = zhongLvSource.getFieldByAlias(entry.getKey());
if (!Objects.isNull(fieldByAlias)) {
constructCommdata(data, entry, fieldByAlias.getCnName(), fieldByAlias.getType());
}
}
formData.setData(data);
}
formDataList.add(formData);
}
return formDataList;
}
- 代码修改后再次追踪,发现已经能够正常获取总条数
总结
使用pagehelper执行分页时,如果中途需要进行数据处理,切记不能丢失从数据库返回的数据类型和相关数据