Java树形结构集合分页
需求
商品类目树数据量大导致加载太慢,需添加一个分页功能。
难点
- 树状结构不能用mybatis-plus自带的分页功能,需自己写分页逻辑
- 因数据量大,需进行缓存处理
实现
第一步:查出所有树形集合数据 (需进行缓存处理)
List<GoodsCategoryTree> resultList = goodsCategoryService.selectTree(null);
List<GoodsCategoryTree> selectTree(GoodsCategory goodsCategory);
selectTree 方法步骤:
判断key是否存在,如果存在,直接取缓存的值 ,不存在就从数据库查出数据,并把值存到redis里。
@Override
public List<GoodsCategoryTree> selectTree(GoodsCategory goodsCategory) {
if(redisTemplate.hasKey(CacheConstants.GOODS_CATEGORY_TREE_KEY)){
log.info("商品类目管理 selectTree cache");
List<GoodsCategoryTree> cacheList = SpringUtils.getBean(RedisCache.class).getCacheList(CacheConstants.GOODS_CATEGORY_TREE_KEY);
return cacheList;
}
log.info("商品类目管理 selectTree db");
List<GoodsCategoryTree> treeList = getTree(this.list(Wrappers.lambdaQuery(goodsCategory)));
if (CollUtil.isNotEmpty(treeList)){
SpringUtils.getBean(RedisCache.class).setCacheList(CacheConstants.GOODS_CATEGORY_TREE_KEY,treeList);
}
return treeList;
}
其中 getTree()如下:
/**
* @Description: 构建树
*/
private List<GoodsCategoryTree> getTree(List<GoodsCategory> entitys) {
List<GoodsCategoryTree> treeList = entitys.stream()
.filter(entity -> !entity.getId().equals(entity.getParentId()))
.sorted(Comparator.comparingInt(GoodsCategory::getSort))
.map(entity -> {
GoodsCategoryTree node = new GoodsCategoryTree();
BeanUtil.copyProperties(entity, node);
return node;
}).collect(Collectors.toList());
return TreeUtil.build(treeList, CommonConstants.PARENT_ID);
}
TreeUtil类:
@UtilityClass
public class TreeUtil {
/**
* 两层循环实现建树
*
* @param treeNodes 传入的树节点列表
* @return
*/
public <T extends TreeNode> List<T> build(List<T> treeNodes, Object root) {
List<T> trees = new ArrayList<>();
for (T treeNode : treeNodes) {
if (root.equals(treeNode.getParentId())) {
trees.add(treeNode);
// trees.sort(Comparator.comparing(TreeNode::getSort));
}
for (T it : treeNodes) {
if (it.getParentId().equals(treeNode.getId())) {
treeNode.addChildren(it);
// treeNode.getChildren().sort(Comparator.comparing(TreeNode::getSort));
}
}
}
return trees;
}
}
第二步:分页 GoodsCategoryController
/**
* 返回树形集合分页数据
*
* @return
*/
@ApiOperation(value = "返回树形集合分页数据")
@GetMapping("/treePage")
public R getGoodsCategoryTree(Page page, GoodsCategory goodsCategory) {
//得到所有数据
List<GoodsCategoryTree> resultList = goodsCategoryService.selectTree(null);
if (resultList != null && resultList.size() > 0) {
page.setTotal(resultList.size());
}
//分页
List<GoodsCategoryTree> finalList = goodsCategoryService.getFinalListByPage(page,resultList);
if (finalList != null && finalList.size() > 0) {
page.setRecords(finalList);
}
return R.ok(page);
}
分页
/** 分页查询类目树
*/
List<GoodsCategoryTree> getFinalListByPage(Page page , List<GoodsCategoryTree> resultList );
getGoodsCategoryTree方法步骤:
参考:java对list集合进行分页
首先把数据根据创建时间倒序排列,再进行分页
@Override
public List<GoodsCategoryTree> getFinalListByPage(Page page, List<GoodsCategoryTree> resultList) {
//根据创建时间倒序排列
List<GoodsCategoryTree> treeList = resultList.stream().sorted(Comparator.comparing(GoodsCategoryTree::getCreateTime).reversed())
.collect(Collectors.toList());
//进行分页
List<GoodsCategoryTree> subList = treeList.stream().skip((page.getCurrent()-1)*page.getSize()).limit(page.getSize()).
collect(Collectors.toList());
return subList;
}
第三步:前端实现
avue-crud 组件加上:page.sync=“page”
<avue-crud
ref="crud"
:data="tableData"
:page.sync="page"
:permission="permissionList"
:table-loading="tableLoading"
:option="tableOption"
:before-open="beforeOpen"
v-model="form"
@on-load="getPage"
@refresh-change="refreshChange"
@row-update="handleUpdate"
@row-save="handleSave"
@row-del="handleDel"
>
data() 加上:
page: {
total: 0, // 总页数
currentPage: 1, // 当前页数
pageSize: 20, // 每页显示多少条
ascs: [], //升序字段
descs: "create_time", //降序字段
},
paramsSearch: {},
date: [],
};
重写getPage()方法:
getPage(page, params) {
this.tableLoading = true;
fetchTree(
Object.assign(
{
current: page.currentPage,
size: page.pageSize,
descs: this.page.descs,
ascs: this.page.ascs,
beginTime: this.date[0],
endTime: this.date[1],
},
params,
this.paramsSearch
)
)
.then((response) => {
let tableData = response.data.data.records;
this.tableData = tableData;
this.page.total = response.data.data.total;
this.page.currentPage = page.currentPage;
this.page.pageSize = page.pageSize;
let parentIdDIC = [
{
id: "0",
name: "顶级分类",
parentId: "0",
},
];
tableData.forEach((item) => {
parentIdDIC.push({
id: item.id,
name: item.name,
parentId: item.parentId,
});
});
this.$refs.crud.DIC.parentId = parentIdDIC;
this.tableLoading = false;
})
.catch(() => {
this.tableLoading = false;
});
},