一、資料庫父子結構資料設計
大部分采用 parentId的形式來存儲父id,并且隻存儲父id,祖父Id不存儲。也可以添加存儲層級級别或者層級關系等字段。
CREATE TABLE `t_resource` (
`id` varchar(255) NOT NULL COMMENT '主鍵',
`parent_id` varchar(255) DEFAULT NULL COMMENT '父ID',
`name` varchar(255) DEFAULT NULL COMMENT '名稱',
`url` varchar(255) DEFAULT NULL COMMENT '資源url',
`level` varchar(255) DEFAULT NULL COMMENT '層級級别',
`decode` varchar(255) DEFAULT NULL COMMENT '層級ID的關系,用”_“分割',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
二、将有父子關系的資料轉換成樹形結構資料
mapper層擷取資料庫資料和 controller層處理很簡單,将有父子關系的資料轉換成樹形結構資料交給 service層處理。
@PostMapping("/getMuneTree")
@ResponseBody
public ResponseEntity<Map<String, Object>> getMuneTree(){
Map<String, Object> map = new HashMap<>();
map.put("menuList", resourceDOService.getMuneTree());
return ResponseEntity.ok(map);
}
1、方式一:遞歸:從樹的最頂級擷取子級,然後子級擷取其子級。
傳回時,需要哪些字段值就添加哪些字段值到 map中。結果圖如上
/**
* 将有父子關系的資料轉換成樹形結構資料
*
* @return 最終的樹狀結構的集合資料
*/
@Override
public List<Map<String, Object>> getMuneTree() {
// 擷取資料庫中帶有有父子關系的資料
List<ResourceDO> data = resourceDOMapper.selectAll();
//建立一個List集合來存放最終的樹狀結構資料
List<Map<String, Object>> menuList = new ArrayList<>();
// 先存入最頂級的樹(0代表沒有父級,即最頂級),然後通過最頂級的id遞歸擷取子級
for (ResourceDO entity : data) {
Map<String, Object> map = new HashMap<>();
if ("0".equals(entity.getParentId())) {
map.put("id", entity.getId());
map.put("parentId", entity.getParentId());
map.put("name", entity.getName());
map.put("children", getChildren(data, entity.getId()));
menuList.add(map);
}
}
return menuList;
}
/**
* 遞歸處理:通過id擷取子級,查詢子級下的子級
*
* @param data 資料庫的原始資料
* @param id 主id
* @return 該id下得子級
*/
public List<Map<String, Object>> getChildren(List<ResourceDO> data, String id) {
List<Map<String, Object>> list = new ArrayList<>();
if (data == null || data.size() == 0 || id == null) {
return list;
}
for (ResourceDO entity : data) {
Map<String, Object> map = new HashMap<>();
//如果本級id與資料的父id相同,就說明是子父級關系
if (id.equals(entity.getParentId())) {
map.put("id", entity.getId());
map.put("parentId", entity.getParentId());
map.put("name", entity.getName());
//查詢子級下的子級
map.put("children", getChildren(data, entity.getId()));
list.add(map);
}
}
return list;
}
2、方式二:組裝帶有children關聯性的對象
在實體列中定義一個 children集合:
private List<ResourceDO> children = new ArrayList<>();
傳回的是實體類對象的所有值,這裡操作的都是集合存儲對象的引用
/**
* 将有父子關系的資料轉換成樹形結構資料
*
* @return 最終的樹狀結構的集合資料
*/
@Override
public List<ResourceDO> getMuneTree2() {
// 擷取資料庫中帶有有父子關系的資料
List<ResourceDO> data = resourceDOMapper.selectAll();
// 複制data資料
List<ResourceDO> menuList = new ArrayList<>(data);
// 周遊兩次data來組裝帶有children關聯性的對象,如果找到子級就删除menuList的資料
for (ResourceDO entity : data) {
for (ResourceDO entity2 : data) {
//如果本級id與資料的父id相同,就說明是子父級關系
if (entity.getId().equals(entity2.getParentId())) {
entity.getChildren().add(entity2);
menuList.remove(entity2);
}
}
}
return menuList;
}
ends~