Java后端将查询数据组装成树结构

本文介绍如何在Java中构建一个物料分类的数据树结构。通过自关联查询获取所有节点,然后递归组装成树形结构,其中最高级父节点的标识为0。查询最高父节点的SQL语句被展示,并且使用了Linq库来过滤子节点。最后,给出了数据组装的效果和所需引入的Linq依赖。
摘要由CSDN通过智能技术生成

场景与实现:一张表的自关联存储,后台一次性查询出所有数据(所有节点数据与最高级父节点数据),

注:再进行组装。这里的最高级父节点的materialtypeParent默认为0。

1、实体类

实体类为BasMaterialType,继承了树公共类TreeEntity,树公共类继承了实体公共字段类BaseDomain。(存在部分注解或字段非组件所必须字段,为了完整性全部CV上来)

  • BasMaterialType
/**
 * 物料分类维护对象 bas_material_type
 * 
 * @author ruoyi
 * @date 2021-04-27
 */
@Data
@ToString
@EqualsAndHashCode
@NoArgsConstructor
@Accessors(chain = true)
@TableName("bas_material_type")
public class BasMaterialType extends TreeEntity
{

    /** 分类主键 */
    @TableId(value = "materialtype_id")
    @JsonFormat(shape = JsonFormat.Shape.STRING)
    private Long materialtypeId;
    
    /** 分类编码 */
    @Excel(name = "分类编码")
    private String materialtypeCode;
    
    /** 分类名称 */
    @Excel(name = "分类名称")
    private String materialtypeName;
    
    /** 分类父级 */
    @Excel(name = "分类父级")
    @JsonFormat(shape = JsonFormat.Shape.STRING)
    private Long materialtypeParent;
    
    /** 分类项次 */
    @Excel(name = "分类项次")
    private Long materialtypeSeq;

}
  • TreeEntity
/**
 * Tree基类
 * 
 * @author ruoyi
 */
public class TreeEntity extends BaseDomain
{
    private static final long serialVersionUID = 1L;

    /** 父菜单名称 */
    @TableField(exist = false)
    private String parentName;

    /** 父菜单ID */
    @TableField(exist = false)
    private Long parentId;

    /** 显示顺序 */
    @TableField(exist = false)
    private Integer orderNum;

    /** 祖级列表 */
    @TableField(exist = false)
    private String ancestors;

    /** 子部门 */
    @TableField(exist = false)
    private List<?> children = new ArrayList<>();

    public String getParentName()
    {
        return parentName;
    }

    public void setParentName(String parentName)
    {
        this.parentName = parentName;
    }

    public Long getParentId()
    {
        return parentId;
    }

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

    public Integer getOrderNum()
    {
        return orderNum;
    }

    public void setOrderNum(Integer orderNum)
    {
        this.orderNum = orderNum;
    }

    public String getAncestors()
    {
        return ancestors;
    }

    public void setAncestors(String ancestors)
    {
        this.ancestors = ancestors;
    }

    public List<?> getChildren()
    {
        return children;
    }

    public void setChildren(List<?> children)
    {
        this.children = children;
    }
}
  • BaseDomain
/**
 * @author Administrator
 */
@Data
@ToString
@NoArgsConstructor
public class BaseDomain {

    /**
     * 创建人
     */
    @TableField(value = "created_user", fill = FieldFill.INSERT)
    private String createdUser;

    /**
     * 创建时间
     */
    @TableField(value = "created_time", fill = FieldFill.INSERT)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createdTime;

    /**
     * 创建人名
     */
    @TableField(value = "created_name", fill = FieldFill.INSERT)
    private String createdName;

    /**
     * 修改人名
     */
    @TableField(value = "updated_user", fill = FieldFill.INSERT_UPDATE)
    private String updatedUser;

    /**
     * 修改时间
     */
    @TableField(value = "updated_time", fill = FieldFill.INSERT_UPDATE)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date updatedTime;

    /**
     * 修改人名
     */
    @TableField(value = "updated_name", fill = FieldFill.INSERT_UPDATE)
    private String updatedName;

    @Version
    @TableField(value = "revision",fill = FieldFill.INSERT)
    private Integer revision;

    /**
     * 备注信息
     */
    @TableField(value = "remark")
    private String remark;

}

2、数据树组装

直接来到组装,其他controller、service、mapper就不写了,提供组装和SQL(查询最高父节点)

  • 组装树形结构

    /**
     * 获取物料分类树结构
     * @return
     */
    @Override
    public List<BasMaterialType> getDischargeTree() {
    	// 查询所有节点
        List<BasMaterialType> basDischargeInfoList = this.list();
        // 查询最高父节点
        List<BasMaterialType> rootNode = basMaterialTypeMapper.selectDischargeTree();
        // 设置子节点
        rootNode.forEach(basDischargeInfo -> {
            basDischargeInfo.setChildren(this.getChildren(basDischargeInfoList,basDischargeInfo.getMaterialtypeId()));
        });
        return rootNode;
    }

    /**
     * 获取根据父节点ID获取子节点
     * @param allNode
     * @param parentId
     * @return
     */
    public List<BasMaterialType> getChildren(List<BasMaterialType> allNode, Long parentId){
    	// 使用Linq匹配出传入父节点的下一级子节点
        List<BasMaterialType> basDischargeInfoList = Linq.of(allNode).where(item->item.getMaterialtypeParent().equals(parentId)).toList();
        /**
         * 2023.02.03 更新
         * 这里可以用流处理,省去引入依赖
         */
         // List<BasMaterialType> basDischargeInfoList = allNode.stream().filter(item -> item.getMaterialtypeParent().equals(parentId)).collect(Collectors.toList());
        if (basDischargeInfoList.size()==0){
            return new ArrayList<>();
        }
        //递归下一级
        basDischargeInfoList.forEach(basDischargeInfo -> {
            basDischargeInfo.setChildren(getChildren(allNode,basDischargeInfo.getMaterialtypeId()));
        });
        return basDischargeInfoList;
    }
  • 查询最高父节点SQL
select 
	materialtype_id, 
	materialtype_code, 
	materialtype_name, 
	materialtype_parent, 
	materialtype_seq, 
	revision, 
	created_user, 
	created_name, 
	created_time, 
	updated_user, 
	updated_name, 
	updated_time, 
	remark 
from bas_material_type
where materialtype_parent = 0

3、组装效果

在这里插入图片描述
在这里插入图片描述

4、后言

  • 使用Linq需要导入的依赖
<!-- Linq -->
<dependency>
    <groupId>com.bestvike</groupId>
    <artifactId>linq</artifactId>
    <version>3.1.0</version>
    <scope>compile</scope>
</dependency>
  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
将List数据转换树形结构的基本思路是首先遍历List,将其中每个节点的父子关系建立起来,然后从根节点开始递归构建整个树形结构。 具体实现步骤如下: 1. 定义节点类,包含节点id、节点名称和子节点列表等属性。 ``` public class TreeNode { private String id; private String name; private List<TreeNode> children; // getter和setter方法 // ... } ``` 2. 遍历List,将每个节点的父子关系建立起来,可以使用Map来存储节点id和对应的节点对象,便于查找父节点。 ``` Map<String, TreeNode> map = new HashMap<>(); for (TreeNode node : list) { map.put(node.getId(), node); String parentId = node.getParentId(); if (parentId != null) { TreeNode parent = map.get(parentId); if (parent != null) { parent.getChildren().add(node); } } } ``` 3. 找到根节点,开始递归构建整个树形结构。 ``` public static TreeNode buildTree(List<TreeNode> list) { // 构建Map,方便查找节点 Map<String, TreeNode> map = new HashMap<>(); for (TreeNode node : list) { map.put(node.getId(), node); } // 找到根节点 TreeNode root = null; for (TreeNode node : list) { if (node.getParentId() == null) { root = node; break; } } // 从根节点开始递归构建整个树形结构 buildSubTree(root, map); return root; } private static void buildSubTree(TreeNode node, Map<String, TreeNode> map) { List<TreeNode> children = node.getChildren(); if (children == null) { return; } // 遍历子节点,递归构建子树 for (TreeNode child : children) { buildSubTree(child, map); } // 根据子节点的顺序重新排序 children.sort(Comparator.comparing(TreeNode::getName)); } ``` 以上就是将List数据转换树行结构的基本实现方法。需要注意的是,这里的代码只是一个简单的示例,实际情况下可能需要根据具体的业务需求进行修改和优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值