一:
字段里有一个parentId,0代表顶级,1是二级,2是三级
查一级分类,在实体类(对标数据库的表)添加一个对象,添加注解,因为这个对象在数据库不存在这个字段。

树形递归查询
java
public List<CategoryEntity> listWithTree() {
//查出所有分类
List<CategoryEntity>entities=baseMapper.selectList(null);
//组装成父子树形结构
//2.1)、找到所有一级分类
List<CategoryEntity> levelMenus = entities.stream()
.filter(e -> e.getParentCid() == 0)
.map((menu) -> {
menu.setChildren(getChildrens(menu, entities));
return menu;
})
.sorted((menu, menu2) -> {
return (menu.getSort() == null ? 0 : menu.getSort()) - (menu2.getSort() == null ? 0 : menu2.getSort());
})
.collect(Collectors.toList());
return levelMenus;
}
//递归查找所有菜单的子菜单
private List<CategoryEntity> getChildrens(CategoryEntity root, List<CategoryEntity> all) {
List<CategoryEntity> children = all.stream().filter(categoryEntity -> {
return categoryEntity.getParentCid().equals(root.getCatId());
}).map(categoryEntity -> {
//1、找到子菜单(递归)
categoryEntity.setChildren(getChildrens(categoryEntity, all));
return categoryEntity;
}).sorted((menu, menu2) -> {
//2、菜单的排序
return (menu.getSort() == null ? 0 : menu.getSort()) - (menu2.getSort() == null ? 0 : menu2.getSort());
}).collect(Collectors.toList());
return children;
}
setchildren是往新增属性list里添加,所以才会有一级嵌套二级嵌套三级
二:
部门有多级部门,比如父部门,子部门
表中parent_dept_no和dept_no是用于构建树形结构的基础,通过这2个字段定义资源的上下级关系,通常添加部门,我们通过程序自动生成编号,生成的编号满足以下规则:
-
1级:100000000000000
-
2级:100001000000000
-
3级:100001001000000
-
4级:100001001001000
-
5级:100001001001001
当我们在需要查询当前1级节点以下所有节点时,就不用再递归查询,使用like "dept_no%"即可。
举个例子:
想要查询100001001000000下所有的部门,我们的查询方式为:
select * from sys_dept where dept_no like '100001001%'
这样就可以查询到100001001000000部门下所有的部门了
我的疑问:同级的不同部门怎么区分?
//构建部门编号,有两种情况,当前父部门编号,有子部门:在已有的子部门的基础上累加 | 没有子部门:新增子部门编号
DeptDto deptDto = DeptDto.builder().parentDeptNo(parentDeptNo).build();
List<DeptVo> deptVoList = deptMapper.selectList(deptDto);
//无下属节点则创建下属节点
if(EmptyUtil.isNullOrEmpty(deptVoList)){
return NoProcessing.createNo(parentDeptNo,false);
}else {
//有下属节点则累加下属节点
Long deptNo = deptVoList.stream().map(dept -> {
return Long.valueOf(dept.getDeptNo());
}).max(Comparator.comparing(i -> i)).get();
return NoProcessing.createNo(String.valueOf(deptNo),true);
}
即当前要创建节点的父节点经过我们查询有别的子节点,我们就累加,即找到子节点的最大一个序号,然后在下面创建序列号的逻辑里累加
比如:100001002000000,累加以后变成100001003000000
java
/***
* 生产层级编号
* @param input 输入编号
* @param peerNode 是否下属节点
* @return
* @return: java.lang.String
*/
public static String createNo(String input,boolean peerNode) {
int step = input.length() / 3;
int supplement = 0;
for (int i =0;i<step;i++ ){
String targetString = input.substring(input.length()-3,input.length());
if ("000".equals(targetString)){
input = input.substring(0,input.length()-3);
supplement++;
}else {
break;
}
}
if (peerNode){
input = String.valueOf(Long.valueOf(input) + 1L);
for (int i =0;i<supplement;i++ ){
input = input+"000";
}
}else {
input = String.valueOf(Long.valueOf(input+"001"));
for (int i =0;i<supplement-1;i++ ){
input = input+"000";
}
}
return input;
}
第一部分:处理尾部连续的"000"
- 计算步长 :
step = input.length() / 3
计算出可以检查多少个三字符子串。 - 循环检查尾部 :从输入字符串的末尾开始,每次取最后三个字符进行检查。
- 如果这三个字符是
"000"
,则将它们移除,并增加supplement
计数器。 - 如果不是
"000"
,则停止检查。
- 如果这三个字符是
第二部分:根据 peerNode
标志调整编号
-
如果
peerNode
为true
:- 将剩余的
input
转换为长整型并加 1。 - 然后根据之前记录的
supplement
数量,向结果中追加相应数量的"000"
。
- 将剩余的
-
如果
peerNode
为false
:- 首先在
input
后面追加"001"
,然后转换为长整型。 - 接着根据
supplement - 1
的值,向结果中追加相应数量的"000"
。
- 首先在
这样可以跟方便的查某一部门的子部门列表
还有一种需求就是查整个部门的树形结构
也是先查所有的,再通过所有的·慢慢拼出树形
java
/**
* 组织部门树形
* @return
*/
@Override
public TreeVo deptTreeVo() {
//获取根节点树形
String parentDeptNo = SuperConstant.ROOT_DEPT_PARENT_ID;
//构建查询条件
DeptDto param = DeptDto.builder()
.dataState(SuperConstant.DATA_STATE_0)
.parentDeptNo(NoProcessing.processString(parentDeptNo))
.build();
//查询部门列表数据
List<DeptVo> deptList = deptMapper.selectList(param);
if(EmptyUtil.isNullOrEmpty(deptList)){
throw new BaseException("部门数据没有定义");
}
//找根节点
DeptVo rootDept = deptList.stream().filter(d -> SuperConstant.ROOT_DEPT_PARENT_ID.equals(d.getParentDeptNo())).collect(Collectors.toList()).get(0);
//返回的部门数据
List<TreeItemVo> treeItemVoList = new ArrayList<>();
//递归调用
recursionTreeItem(treeItemVoList,rootDept,deptList);
return TreeVo.builder().items(treeItemVoList).build();
}
/**
* 递归调用拼装数据
* @param treeItemVoList 封装返回的数据
* @param rootDept 当前部门
* @param deptList 部门列表(全部数据)
*/
private void recursionTreeItem(List<TreeItemVo> treeItemVoList, DeptVo rootDept, List<DeptVo> deptList) {
//构建item对象
TreeItemVo treeItemVo = TreeItemVo.builder().id(rootDept.getDeptNo()).label(rootDept.getDeptName()).build();
//获得当前部门下的子部门
List<DeptVo> childrenDept = deptList.stream()
.filter(n -> n.getParentDeptNo().equals(rootDept.getDeptNo()))
.collect(Collectors.toList());
//如果子部门不为空,则继续递归调用
if(!EmptyUtil.isNullOrEmpty(childrenDept)){
ArrayList<TreeItemVo> listChildren = Lists.newArrayList();
//子部门列表
childrenDept.forEach(dept -> {
this.recursionTreeItem(listChildren,dept,deptList);
});
treeItemVo.setChildren(listChildren);
}
treeItemVoList.add(treeItemVo);
}