部門管理系統設計
題目要求
- 設計部門 MySQL 數據表
- 實現接口:根據中間部門 ID 獲取其下屬葉子部門 ID
- 設計包含子節點列表的 Java 數據對象,并實現批量獲取功能
一、MySQL 部門表設計
表結構
CREATE TABLE department (id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '部門ID',name VARCHAR(100) NOT NULL COMMENT '部門名稱',parent_id BIGINT COMMENT '父部門ID,頂級部門為NULL',is_leaf TINYINT(1) DEFAULT 0 COMMENT '是否為葉子部門:0-否,1-是',FOREIGN KEY (parent_id) REFERENCES department(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='部門表';
字段說明
id
: 主鍵,部門唯一標識name
: 部門名稱parent_id
: 父部門關聯IDis_leaf
: 葉子節點標識(可選)
優化建議
可選擇動態計算葉子節點:
SELECT COUNT(*) FROM department WHERE parent_id = ?
二、獲取葉子部門接口實現
簡單的獲取當前節點下的葉子節點:
SELECT d.id, d.name, d.is_leaf
FROM department d
WHERE d.parent_id = 2; -- 技術部的 id 是 2
遞歸查詢方案,查詢當前節點及其子節點下所有的葉子節點(MySQL 8.0+)
WITH RECURSIVE dept_tree AS (-- 基礎查詢:選出指定的幾個部門(比如傳入的中間部門 ids)SELECT id, parent_id, is_leafFROM departmentWHERE id IN (1) -- 🔹輸入的部門ID,可以是中間部門或任意部門UNION ALL-- 遞歸查詢:找出這些部門的子部門,再子部門的子部門...(無限層級往下遍歷)SELECT d.id, d.parent_id, d.is_leafFROM department dJOIN dept_tree dt ON d.parent_id = dt.id
)
-- 最終查詢:從遞歸結果中,篩選出 is_leaf = 1 的部門,即葉子節點
SELECT id
FROM dept_tree
WHERE is_leaf = 1;
三、Java 數據對象設計與批量獲取功能實現
1. Java 數據對象設計(包含子節點列表)
我們設計一個 Department 類,用于表示部門信息,并包含其子部門列表,以支持樹形結構的構建。
import java.util.ArrayList;
import java.util.List;/*** 部門實體類,包含子節點列表,用于構建部門樹結構*/
public class Department {private Long id;private String name;private Long parentId;private Boolean isLeaf;private List<Department> children; // 子部門列表// 構造函數// Getter 和 Setter 方法public List<Department> getChildren() {return children;}public void setChildren(List<Department> children) {this.children = children;}// 添加子節點public void addChild(Department child) {this.children.add(child);}
}
2. 批量獲取葉子部門 ID 的功能實現
我們提供一個服務類 DepartmentService,其中包含如下功能:
? 根據中間部門 ID 獲取其下屬所有葉子部門 ID
? 批量獲取多個中間部門的葉子部門 ID
? 構建部門樹(可選,用于前端展示等場景)
2.1 Service 接口定義
import java.util.List;public interface DepartmentService {/*** 根據中間部門ID,獲取其下屬所有葉子部門的ID列表* @param parentId 中間部門ID* @return 葉子部門ID集合*/List<Long> getLeafDepartmentIds(Long parentId);/*** 批量獲取多個中間部門ID下屬的所有葉子部門ID* @param parentIds 中間部門ID集合* @return Map<中間部門ID, 葉子部門ID列表>*/Map<Long, List<Long>> getLeafDepartmentIdsBatch(List<Long> parentIds);/*** 獲取所有部門數據(用于構建樹或遞歸查詢,可從數據庫加載)* @return 部門列表*/List<Department> getAllDepartments();/*** 構建部門樹結構(可選功能,用于展示等)* @param departments 所有部門列表* @return 樹形結構的部門列表(通常只有根節點或一級節點)*/List<Department> buildDepartmentTree(List<Department> departments);
}
2.2 Service 實現類
import org.springframework.stereotype.Service;import java.util.*;
import java.util.stream.Collectors;@Service
public class DepartmentServiceImpl implements DepartmentService {// 模擬從數據庫中獲取所有部門信息(實際應從數據庫查詢,比如使用JPA、MyBatis等)@Overridepublic List<Department> getAllDepartments() {// 這里模擬數據,實際應從數據庫查詢List<Department> departments = new ArrayList<>();departments.add(new Department(1L, "總公司", null, false));departments.add(new Department(2L, "技術部", 1L, false));departments.add(new Department(3L, "產品部", 1L, false));departments.add(new Department(4L, "前端組", 2L, true));departments.add(new Department(5L, "后端組", 2L, true));departments.add(new Department(6L, "UI組", 3L, true));departments.add(new Department(7L, "測試組", 2L, true));return departments;}/*** 獲取指定父部門下所有葉子部門的ID*/@Overridepublic List<Long> getLeafDepartmentIds(Long parentId) {List<Department> allDepts = getAllDepartments();return findLeafIds(allDepts, parentId);}/*** 批量獲取多個父部門下的所有葉子部門ID*/@Overridepublic Map<Long, List<Long>> getLeafDepartmentIdsBatch(List<Long> parentIds) {List<Department> allDepts = getAllDepartments();Map<Long, List<Long>> result = new HashMap<>();for (Long parentId : parentIds) {List<Long> leafIds = findLeafIds(allDepts, parentId);result.put(parentId, leafIds);}return result;}/*** 遞歸查找某個父部門下所有的葉子部門ID*/private List<Long> findLeafIds(List<Department> departments, Long parentId) {List<Long> leafIds = new ArrayList<>();// 找出直接子部門for (Department dept : departments) {if (Objects.equals(dept.getParentId(), parentId)) {if (dept.getIsLeaf() != null && dept.getIsLeaf()) {// 是葉子節點leafIds.add(dept.getId());} else {// 非葉子節點,遞歸查找leafIds.addAll(findLeafIds(departments, dept.getId()));}}}return leafIds;}/*** 構建部門樹結構(可選,用于前端樹形展示)*/@Overridepublic List<Department> buildDepartmentTree(List<Department> departments) {// 找出所有根節點(parent_id is null)List<Department> roots = departments.stream().filter(d -> d.getParentId() == null).collect(Collectors.toList());// 遞歸構建子節點for (Department root : roots) {buildChildren(root, departments);}return roots;}/*** 遞歸設置子節點*/private void buildChildren(Department parent, List<Department> allDepartments) {List<Department> children = allDepartments.stream().filter(d -> Objects.equals(d.getParentId(), parent.getId())).collect(Collectors.toList());for (Department child : children) {parent.addChild(child);buildChildren(child, allDepartments); // 遞歸查找子節點的子節點}}
}
3. 接口調用示例(Controller 示例,可選)
如果你使用 Spring Boot,可以提供一個 REST 接口來調用上述服務:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;import java.util.List;
import java.util.Map;@RestController
@RequestMapping("/api/departments")
public class DepartmentController {@Autowiredprivate DepartmentService departmentService;/*** 獲取某個部門下的所有葉子部門ID*/@GetMapping("/leaf-ids/{parentId}")public List<Long> getLeafIds(@PathVariable Long parentId) {return departmentService.getLeafDepartmentIds(parentId);}/*** 批量獲取多個部門下的所有葉子部門ID*/@PostMapping("/leaf-ids/batch")public Map<Long, List<Long>> getLeafIdsBatch(@RequestBody List<Long> parentIds) {return departmentService.getLeafDepartmentIdsBatch(parentIds);}/*** 獲取完整的部門樹結構(可選)*/@GetMapping("/tree")public List<Department> getDepartmentTree() {List<Department> allDepts = departmentService.getAllDepartments();return departmentService.buildDepartmentTree(allDepts);}
}
四、總結
功能 實現內容
MySQL 表設計 包含 id、name、parent_id、is_leaf 字段,支持層級與葉子標識
遞歸查詢葉子部門 SQL(MySQL 8.0+) 使用 WITH RECURSIVE 查詢指定部門下所有葉子節點
Java 實體類 Department 類,包含子節點列表 children,支持樹形結構
批量獲取葉子部門ID Service 層提供根據父部門 ID(或批量)查詢所有葉子部門 ID 的功能,支持遞歸查找
可選功能 構建完整的部門樹結構,便于前端展示;提供 REST 接口調用
五、擴展建議
- 緩存優化:對于部門數據不頻繁變動的場景,可使用 Redis 緩存部門樹或葉子部門關系,提高查詢效率。
- 數據庫索引優化:為 parent_id 字段添加索引,加快查詢速度。
- 動態 is_leaf:如果不想手動維護 is_leaf 字段,可通過查詢是否有子部門來動態判斷是否為葉子節點。
- 異步加載:對于大型部門樹,可考慮懶加載/異步加載子節點,提升用戶體驗。
如你還需要 MyBatis 或 JPA 的具體實現、前端樹形組件對接、遞歸性能優化等,可以繼續提問!