1、数据库必要表结构

组织树表

 

公司表(包含集团、子公司、分公司等)

 项目表

2、数据库数据:

组织树表

公司表

 

项目表

 

 

 

 

2、 树形结构代码:

import java.util.*;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jianke.tree.api.domain.ITree;
import org.apache.commons.collections4.CollectionUtils;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jianke.tree.TreeApplication;
import com.jianke.tree.api.domain.SysOrganizationTree;
import com.jianke.tree.service.impl.SysOrganizationTreeServiceImpl;

/**
* <p>
* 测试树
* </p>
*
*/
@SpringBootTest(classes = TreeApplication.class)
public class Main {
@Autowired
private SysOrganizationTreeServiceImpl sysOrganizationTreeService;

@Test
public void test() throws JsonProcessingException {
Long startTime;
Long endTime;
//生成树测试
startTime = System.currentTimeMillis();
List<SysOrganizationTree> genTrees = beforeAndInitTree();
endTime = System.currentTimeMillis();
System.out.println("耗时:"+(endTime-startTime)+"毫秒,"+" 子节点个数:" +genTrees.size());
//把list树转为json串给前端
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(genTrees);
System.out.println("json= " + json);
}

public List<SysOrganizationTree> beforeAndInitTree(){
     //这里的查询可以根据自己的要求拼接好前端需要展示或使用的列名后传入到newInitTree方法中,只用新增一个返回的VO包含所有列即可
List<SysOrganizationTree> source = sysOrganizationTreeService.list(new QueryWrapper<SysOrganizationTree>().lambda()
.eq(SysOrganizationTree::getIsDelete, 0));
return newInitTree(source);
}

//抽离成Itree接口
public <T extends ITree> List<T> newInitTree(List<T> source) {
List<T> res = new ArrayList<>();
Map<Object, T> map = new HashMap<>();
LinkedList<T> list = new LinkedList<T>(source);
//以下代码逻辑:1、如果list中的当前值已经在map中找到父节点就挂上去,并移除掉当前的list值;如果map中没有父节点,则先加到map中再加回到list;
// 2、如果list中的当前值已经在map中找到父节点就挂上去,并移除掉当前的list值;同时把移除的值挂到对应map中的对应父节点下去;循环如此直到list所有的值都挂到父节点去
while (CollectionUtils.isNotEmpty(list)) {
T obj = list.pop();
map.put(obj.getCode(), obj);
Object parentId = obj.getParentCode();
T parentTree = map.get(parentId);
if (null != parentTree) {//如果有父节点,则挂到父节点
if (null == parentTree.getChildren()) {
parentTree.setChilds(new ArrayList<>());
}
parentTree.getChildren().add(obj);
} else if (Objects.equals(parentId, 3L)) {//添加根节点,parentId等于3的数据到list集合res中
res.add(obj);
} else {//如果map中没有父节点,则加回到list
list.add(obj);
}
}
return res;
}
}



package com.jianke.tree.api.domain;

import java.util.Date;
import java.util.List;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

/**
* 组织树
*/
@ApiModel("组织树")
public class SysOrganizationTree implements ITree<SysOrganizationTree> {
/** 主键 */
@TableId(value = "id", type = IdType.ASSIGN_ID)
@ApiModelProperty("自增id")
private Long id;
/** 节点ID */
@ApiModelProperty("节点id")
private Long resourceId;
/** 父节点ID */
@ApiModelProperty("父节点id")
private Long parentId;
/** 节点名称 */
@ApiModelProperty("节点名称")
private String name;
/** 节点类型 */
@ApiModelProperty("节点类型")
private Integer type;
/** 创建者 */
private Long createBy;
/** 创建时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date gmtCreate;
/** 更新者 */
private Long updateBy;
/** 更新时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date gmtModified;
/** 删除标志(0代表存在 2代表删除) */
@ApiModelProperty("删除标志(0代表存在 2代表删除)")
private int isDelete;
/** 数据状态:0正常,1停用 */
@ApiModelProperty("数据状态:0正常,1停用 ")
private int status;
@TableField(exist = false)
@JsonIgnore
private List<SysOrganizationTree> parent;
// @JsonIgnore
@TableField(exist = false)
private List<SysOrganizationTree> children;

public List<SysOrganizationTree> getParent() {
return parent;
}

public void setParent(List<SysOrganizationTree> parent) {
this.parent = parent;
}

public void setChildren(List<SysOrganizationTree> children) {
this.children = children;
}

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public Long getResourceId() {
return resourceId;
}

public void setResourceId(Long resourceId) {
this.resourceId = resourceId;
}

public Long getParentId() {
return parentId;
}

public void setParentId(Long parentId) {
this.parentId = parentId;
}

@Override
public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Integer getType() {
return type;
}

public void setType(Integer type) {
this.type = type;
}

public Long getCreateBy() {
return createBy;
}

public void setCreateBy(Long createBy) {
this.createBy = createBy;
}

public Long getUpdateBy() {
return updateBy;
}

public void setUpdateBy(Long updateBy) {
this.updateBy = updateBy;
}

public Date getGmtCreate() {
return gmtCreate;
}

public void setGmtCreate(Date gmtCreate) {
this.gmtCreate = gmtCreate;
}

public Date getGmtModified() {
return gmtModified;
}

public void setGmtModified(Date gmtModified) {
this.gmtModified = gmtModified;
}

public int getIsDelete() {
return isDelete;
}

public void setIsDelete(int isDelete) {
this.isDelete = isDelete;
}

public int getStatus() {
return status;
}

public void setStatus(int status) {
this.status = status;
}

@Override
public Long getParentCode() {
return parentId;
}

@Override
public Long getCode() {
return resourceId;
}

@Override
public List<SysOrganizationTree> getChildren() {
return children;
}

@Override
public void setChilds(List<SysOrganizationTree> list) {
children = list;
}
}


package com.jianke.tree.api.domain;

import java.util.List;


/**
* ITree接口,里面定义getParentCode 、getCode、getChilds、setChilds 等方法,
* 然后新的entity继承,并重写这些方法,生成树的方法写得较为解耦
* */
public interface ITree<T>{
//获取子节点
List<T> getChildren();
//设置子节点
void setChilds(List<T> list);
//获取父节点ID
Object getParentCode();
//获取ID
Object getCode();
//获取名字
Object getName();
}

格式有点丑,复制就能测试并使用,图片转文字可以搜索:讯飞图片转文字