需求:有多级目录,而目录的层级是不固定的,如下图所示:
数据结构:
sql语句:
<select id="getList" resultType="com.hikvision.idatafusion.dhidata.bean.vo.knowledgebase.KnowledgeBaseTypeTreeVo">
with recursive tree as(
select distinct kbt.id, kbt.type_name, kbt.type_sort, kbt.parent_id, 1 as type_level,
kbt.id::text as id_path, kbt.type_name::text as type_name_path, kbt.type_sort::text as type_sort_path
from knowledge_base_type kbt
<if test="excludeNoDataType">
join knowledge_base kb on kb.delete_flag = 0 and kb.type_id_list <![CDATA[&&]]> array[kbt.id]::int8[]
and kb.publish_state = '1'
</if>
where kbt.delete_flag = 0
union
select tree.id, tree.type_name, tree.type_sort, parent.parent_id, tree.type_level + 1 as type_level,
concat(parent.id, '/', tree.id_path) as id_path,
concat(parent.type_name, '/', tree.type_name_path) as type_name_path,
concat(parent.type_sort, '/', tree.type_sort_path) as type_sort_path
from tree
join knowledge_base_type parent on parent.delete_flag = 0 and parent.id = tree.parent_id
)
select id, type_name, type_sort, type_level, id_path, type_name_path, type_sort_path
from (
select *, ROW_NUMBER() OVER (PARTITION BY id ORDER BY type_level desc) AS rn from tree
) t
where t.rn = 1
</select>
业务处理 :
/**
* 是否排除没有数据的分类
*/
@Override
public List<KnowledgeBaseTypeTreeVo> getList(boolean excludeNoDataType) {
KnowledgeBaseTypeQueryDto knowledgeBaseTypeQueryDto = new KnowledgeBaseTypeQueryDto();
knowledgeBaseTypeQueryDto.setExcludeNoDataType(excludeNoDataType);
List<KnowledgeBaseTypeTreeVo> knowledgeBaseTypeTreeVoList = knowledgeBaseTypeDao.getList(knowledgeBaseTypeQueryDto);
// 对分类进行分层、排序
Map<Long, KnowledgeBaseTypeTreeVo> firstLevelMap = new HashMap<>(); // 一级分类
for (KnowledgeBaseTypeTreeVo knowledgeBaseType : knowledgeBaseTypeTreeVoList) {
String[] idPath = knowledgeBaseType.getIdPath().split("/");
// 生成一级分类
long firstLevelId = Long.parseLong(idPath[0]);
if(!firstLevelMap.containsKey(firstLevelId)) {
KnowledgeBaseTypeTreeVo firstLevel = new KnowledgeBaseTypeTreeVo();
firstLevel.setId(firstLevelId);
firstLevel.setTypeName(knowledgeBaseType.getTypeNamePath().split("/")[0]);
firstLevel.setTypeSort(Integer.parseInt(knowledgeBaseType.getTypeSortPath().split("/")[0]));
firstLevel.setParentId(knowledgeBaseType.getParentId());
firstLevelMap.put(firstLevelId, firstLevel);
}
// 遍历生成二级、三级...分类
KnowledgeBaseTypeTreeVo firstLevel = firstLevelMap.get(firstLevelId); // 一级
Map<Long, KnowledgeBaseTypeTreeVo> childrenMap = firstLevel.getChildrenMap();
for (int i = 1; i < idPath.length; i++) { // 从二级开始遍历
long typeId = Integer.parseInt(idPath[i]);
if(!childrenMap.containsKey(typeId)) {
KnowledgeBaseTypeTreeVo treeVo = new KnowledgeBaseTypeTreeVo();
treeVo.setId(typeId);
treeVo.setTypeName(knowledgeBaseType.getTypeNamePath().split("/")[i]);
treeVo.setTypeSort(Integer.parseInt(knowledgeBaseType.getTypeSortPath().split("/")[i]));
treeVo.setParentId((long) Integer.parseInt(idPath[i-1]));
childrenMap.put(typeId, treeVo);
}
childrenMap = childrenMap.get(typeId).getChildrenMap(); // 下一级
}
// 排序
for(KnowledgeBaseTypeTreeVo firstKnowledgeBaseType : firstLevelMap.values()) {
this.sortChildren(firstKnowledgeBaseType);
}
knowledgeBaseType.setChildrenMap(firstLevelMap);
}
// 结果处理后返回
List<KnowledgeBaseTypeTreeVo> knowledgeBaseTypeTreeList = firstLevelMap.values().stream().collect(Collectors.toList());
return knowledgeBaseTypeTreeList;
}
/*
* 分类按TypeSort倒序
* */
private void sortChildren(KnowledgeBaseTypeTreeVo treeVo) {
if(MapUtils.isEmpty(treeVo.getChildrenMap())) {
return;
}
treeVo.setChildren(treeVo.getChildrenMap().values().stream().
sorted(Comparator.comparingInt(KnowledgeBaseTypeTreeVo::getTypeSort).reversed()).collect(Collectors.toList()));
for(KnowledgeBaseTypeTreeVo child: treeVo.getChildrenMap().values()) {
sortChildren(child);
}
}
返回数据实体类:
@Data
@ToString
@EqualsAndHashCode(callSuper = false)
public class KnowledgeBaseTypeTreeVo implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "ID")
private Long id;
@ApiModelProperty(value = "类型名称")
private String typeName;
@ApiModelProperty(value = "序号,排序")
private Integer typeSort;
@ApiModelProperty(value = "父节点ID")
public Long parentId;
@ApiModelProperty(value = "分类层级")
private Integer typeLevel;
@ApiModelProperty(value = "分类ID层级路径")
private String idPath;
@ApiModelProperty(value = "分类名称层级路径")
private String typeNamePath;
@ApiModelProperty(value = "分类排序层级路径")
private String typeSortPath;
@ApiModelProperty(value = "子分类")
private List<KnowledgeBaseTypeTreeVo> children = new ArrayList();
@ApiModelProperty(value = "分类")
private Map<Long, KnowledgeBaseTypeTreeVo> childrenMap = new HashMap<>();
}