场景与实现:一张表的自关联存储,后台一次性查询出所有数据(所有节点数据与最高级父节点数据),
注:再进行组装。这里的最高级父节点的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>