Java 实现目录层级树
需求:
扁平化的数据库存储 转换成有层级的树。放一张图,更容易理解

- controller
@RestController
@RequestMapping("/catalogue")
public class CatalogueController {
@Autowired
CatalogueService catalogueService;
@PostMapping("/getStudentsInfo")
public RestResponse<Object> getStudentsInfo(@RequestBody StudentRequest studentRequest){
List<CatalogueDTO> studentDTOList = catalogueService.getCatalogueTree();
return RestResponse.ok(studentDTOList);
}
}
- Services接口 && Services实现类
public interface CatalogueService {
List<CatalogueDTO> getCatalogueTree();
}
@Service
public class CatalogueServiceImpl implements CatalogueService {
@Autowired
CatalogueMapepr catalogueMapepr;
@Override
public List<CatalogueDTO> getCatalogueTree() {
List<CatalogueDO> catalogueDOList = catalogueMapepr.getCatalogueTree();
// 此处是使用 mapstruct 的方式进行对象的copy 类似与 BeanUtils.copyProperties();
List<CatalogueDTO> catalogueDtos= StudentConverter.INSTANCE.doToDto(catalogueDOList);
// 获取顶层目录
List<CatalogueDTO> topCatalogue = catalogueDtos.stream().filter(item -> item.getParentId() == null).collect(Collectors.toList());
// 获取非顶层目录通过目录parentId做分组
Map<Long, List<CatalogueDTO>> catalogueMap = catalogueDtos.stream()
.filter(e -> e.getParentId() != null)
.collect(Collectors.groupingBy(CatalogueDTO::getParentId));
setChildren(topCatalogue,catalogueMap);
return topCatalogue;
}
/**
* 这种查询目录两个关键地方:递归 && 设置子集 从两个角度思考问题
* 类比mybatis的嵌套子查询 孩子
*/
public void setChildren(List<CatalogueDTO> catalogueDTO, Map<Long, List<CatalogueDTO>> catalogueMap) {
for (CatalogueDTO dto : catalogueDTO) {
List<CatalogueDTO> childrenDtos = catalogueMap.getOrDefault(dto.getCatalogueId(),Lists.newArrayList());
dto.setChildrenDTO(childrenDtos);
setChildren(childrenDtos,catalogueMap);
}
}
}
- Mapper接口
public interface CatalogueMapepr {
/**
* 查询所有的目录信息
*
* @return CatalogueDO
*/
List<CatalogueDO> getCatalogueTree();
}
- xml:sql
<resultMap id="catalogueResultMap" type="it.hww.entity.CatalogueDO" autoMapping="true">
</resultMap>
<select id="getCatalogueTree" resultMap="catalogueResultMap">
select * from meta_catalogue
</select>
- 数据表
CREATE TABLE `meta_catalogue` (
`catalogue_id` bigint(20) NOT NULL,
`catalogue_code` varchar(32) COLLATE utf8_bin DEFAULT NULL COMMENT '目录编码/英文名',
`catalogue_name` varchar(32) COLLATE utf8_bin DEFAULT NULL COMMENT '目录名称',
`catalogue_status` varchar(2) COLLATE utf8_bin DEFAULT NULL COMMENT '状态 0:不可用、1:可用 ',
`parent_id` bigint(20) DEFAULT NULL COMMENT '父id',
`sort` int(32) DEFAULT NULL COMMENT '序号',
`id_path` varchar(255) COLLATE utf8_bin DEFAULT NULL COMMENT 'id路径',
`name_path` varchar(255) COLLATE utf8_bin DEFAULT NULL COMMENT '名称路径',
`create_by` varchar(32) CHARACTER SET utf8 DEFAULT NULL COMMENT '创建人',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_by` varchar(32) CHARACTER SET utf8 DEFAULT NULL COMMENT '更新人',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
`is_active` tinyint(1) DEFAULT NULL COMMENT '是否有效',
PRIMARY KEY (`catalogue_id`) USING BTREE,
UNIQUE KEY ```catalogue_id``` (`catalogue_id`) USING BTREE,
KEY ```parent_id``` (`parent_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin ROW_FORMAT=DYNAMIC COMMENT='目录管理主表';
- 数据对象
@Data
public class CatalogueDO {
private Long catalogueId;
private String catalogueCode;
private String catalogueName;
private Long parentId;
private String idPath;
private String namePath;
}
@Data
public class CatalogueDTO{
private Long catalogueId;
private String catalogueCode;
private String catalogueName;
private Long parentId;
private String idPath;
private String namePath;
private List<CatalogueDTO> childrenDTO;
}
- 此接口的作用就是把StudentDO转换成StudentDTO
@Mapper
public interface StudentConverter {
StudentConverter INSTANCE = Mappers.getMapper(StudentConverter.class);
/**
* 实体之间转换
* @param studentDO
* @return StudentDTO
*/
StudentDTO do2dto(StudentDO studentDO);
/**
* catalogueDOList--> CatalogueDTOList
*
* @param catalogueDOList catalogueDOList
* @return CatalogueDTOList
*/
List<CatalogueDTO> doToDto(List<CatalogueDO> catalogueDOList);
CatalogueDTO doToDtoOne(CatalogueDO catalogueDO);
}
智商不是瓶颈,更需要坚韧和毅力。

浙公网安备 33010602011771号