通过迭代器构建树状结构数据
需求:前端需要如图树状结构的数据
表以parent_id字段分级,0为1级目录,1为2级目录…
常规可以自连接使用associate和collection构建一个数据集合的实体类,按照所需的数据格式进行连表雨构建。
问题:mapper会非常复杂,特别是在表字段多,关联表多的时候,工作量会非常大。
思路:此时我们可以从构建数据集合方面着手,将表中的数据进行提取(循环递归),按所需格式进行重新排列。组成新的集合并写成一个通用的方法,可大大提高效率。
代码部分:
/** * 构建前端所需要树结构 * * @param depts 部门列表 * @return 树结构列表 */ @Override public List<SysDept> buildDeptTree(List<SysDept> depts) { List<SysDept> returnList = new ArrayList<SysDept>(); List<Long> tempList = new ArrayList<Long>(); for (SysDept dept : depts) { //循环添加id到Long数组中 tempList.add(dept.getDeptId()); } //构建SysDept迭代器 for (Iterator<SysDept> iterator = depts.iterator(); iterator.hasNext();) { SysDept dept = (SysDept) iterator.next(); // 如果是顶级节点, 遍历该父节点的所有子节点 if (!tempList.contains(dept.getParentId()))//如果该节点没有父节点 { recursionFn(depts, dept);//调用递归方法,设置子节点 returnList.add(dept);//将处理好的dept添加到数组中 } } if (returnList.isEmpty()) { returnList = depts; } return returnList; }
/** * 构建前端所需要下拉树结构 * * @param depts 部门列表 * @return 下拉树结构列表 */ @Override public List<TreeSelect> buildDeptTreeSelect(List<SysDept> depts) { List<SysDept> deptTrees = buildDeptTree(depts); return deptTrees.stream().map(TreeSelect::new).collect(Collectors.toList()); }
/** * 根据ID查询所有子部门(正常状态) * * @param deptId 部门ID * @return 子部门数 */ @Override public int selectNormalChildrenDeptById(Long deptId) { return deptMapper.selectNormalChildrenDeptById(deptId); } /** * 是否存在子节点 * * @param deptId 部门ID * @return 结果 */ @Override public boolean hasChildByDeptId(Long deptId) { int result = deptMapper.hasChildByDeptId(deptId); return result > 0 ? true : false; }
/** * 递归列表 */ private void recursionFn(List<SysDept> list, SysDept t) { // 得到子节点列表 List<SysDept> childList = getChildList(list, t); t.setChildren(childList); for (SysDept tChild : childList) { if (hasChild(list, tChild)) { recursionFn(list, tChild); } } }
/** * 得到子节点列表 */ private List<SysDept> getChildList(List<SysDept> list, SysDept t) { List<SysDept> tlist = new ArrayList<SysDept>(); Iterator<SysDept> it = list.iterator(); while (it.hasNext()) { SysDept n = (SysDept) it.next(); if (StringUtils.isNotNull(n.getParentId()) && n.getParentId().longValue() == t.getDeptId().longValue()) { tlist.add(n); } } return tlist; } /** * 判断是否有子节点 */ private boolean hasChild(List<SysDept> list, SysDept t) { return getChildList(list, t).size() > 0 ? true : false; }
/** * 修改子元素关系 * * @param deptId 被修改的部门ID * @param newAncestors 新的父ID集合 * @param oldAncestors 旧的父ID集合 */ public void updateDeptChildren(Long deptId, String newAncestors, String oldAncestors) { List<SysDept> children = deptMapper.selectChildrenDeptById(deptId); for (SysDept child : children) { child.setAncestors(child.getAncestors().replaceFirst(oldAncestors, newAncestors)); } if (children.size() > 0) { deptMapper.updateDeptChildren(children); } }
这样,我们在service实现层直接调用buildDeptTree方法,将表单所需的数据集合传入进去,无需连表与处理,将得到的数据传给前台即可。