当前位置: 首页 > news >正文

如何在 Spring Boot 中设计和返回树形结构的组织和部门信息

如何在 Spring Boot 中设计和返回树形结构的组织和部门信息

文章目录

  • 如何在 Spring Boot 中设计和返回树形结构的组织和部门信息
      • 1. 需求分析
    • 一、数据库表设计
        • 1.1 `organization` 表设计
        • 1.2 `department` 表设计
        • 1.3 模拟数据
    • 二、后端设计
      • 2.1 实体类设计
        • `Organization` 实体类
        • `Department` 实体类
      • 2.2 DTO 类设计
        • `OrganizationDTO`
        • `DepartmentDTO`
      • 2.3 Service 层设计
      • 2.4 Controller 层设计
    • 三、前端请求与展示
      • 总结

在企业管理系统中,组织和部门之间通常存在层级结构,每个组织和部门都可能有多个子级和父级。这种树形结构的数据管理在很多业务场景下都十分常见,比如权限控制、员工管理等。

今天我们将深入探讨如何在 Spring Boot 中设计组织和部门表,如何在后端生成并返回树形结构数据,以及如何展示组织和部门的完整信息。

1. 需求分析

我们需要设计两个表:组织表organizations)和部门表departments)。两张表之间存在如下关系:

  • 每个组织可以有一个父组织,也可以有多个子组织,形成树形结构。
  • 每个部门属于某个组织,并且每个部门也有可能有子部门,部门之间同样需要支持树形结构。
  • 前端需要通过接口获取组织和部门的树形结构数据,后端通过递归算法构建树形层级。

一、数据库表设计

首先,我们需要设计两张表:organizationdepartmentorganization 表用于存储组织的信息,department 表用于存储部门的信息。两张表都需要支持树形结构的关系。


1.1 organization 表设计
  • organization 表用于存储组织的基本信息,并支持组织的树形层级关系。
  • 每个组织可以有一个父组织,也可以有多个子组织。
  • 通过 parent_id 字段,我们可以表示组织之间的父子关系。
CREATE TABLE `organization` (`id` BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '组织ID',`name` VARCHAR(255) NOT NULL COMMENT '组织名称',`description` VARCHAR(255) COMMENT '组织描述',`location` VARCHAR(255) COMMENT '组织位置',`parent_id` BIGINT DEFAULT NULL COMMENT '父组织ID',`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',CONSTRAINT `fk_parent_org` FOREIGN KEY (`parent_id`) REFERENCES `organization` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
1.2 department 表设计
  • department 表用于存储部门信息,支持部门的树形层级关系。每个部门也可以有一个父部门,也可以有多个子部门。
  • 同时,每个部门属于一个组织, 部门关联到一个组织。
  • organization_id 是部门所属的组织。
  • parent_id 是部门的父级部门。
CREATE TABLE `department` (`id` BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '部门ID',`name` VARCHAR(255) NOT NULL COMMENT '部门名称',`description` VARCHAR(255) COMMENT '部门描述',`employee_count` INT DEFAULT 0 COMMENT '员工数量',`organization_id` BIGINT NOT NULL COMMENT '所属组织ID',`parent_id` BIGINT DEFAULT NULL COMMENT '父部门ID',`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',CONSTRAINT `fk_org_id` FOREIGN KEY (`organization_id`) REFERENCES `organization` (`id`) ON DELETE CASCADE,CONSTRAINT `fk_parent_dep` FOREIGN KEY (`parent_id`) REFERENCES `department` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
1.3 模拟数据

接下来我们可以插入一些模拟数据,以便于我们在后续实现中测试树形结构。

-- 插入组织数据
INSERT INTO `organization` (`name`, `description`, `location`,`parent_id`) VALUES
('总公司', '总部组织', '上海', NULL);
('分公司A', '分公司A', '北京', 1);
('分公司B', '分公司B', '深圳', 1);
('分公司C', '分公司C', '杭州', 2);-- 插入部门数据
INSERT INTO `department` (`name`, `description`, `employee_count`, `organization_id`, `parent_id`) VALUES
('总部', '总部部门', 20, 1, NULL),
('人事部', '管理人力资源', 5, 1, 1),
('IT部', '技术支持部门', 10, 1, 1),
('市场部', '市场推广部门', 5, 1, 1),
('分公司A', '分公司A部门', 30, 2, NULL),
('市场部A', '市场部A', 5, 2, 5);

二、后端设计

2.1 实体类设计

在 Spring Boot 中,我们需要根据数据库表设计对应的实体类。

Organization 实体类
import javax.persistence.*;
import java.util.List;@Entity
public class Organization {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String name;private String description;private String location;@ManyToOne@JoinColumn(name = "parent_id")private Organization parent;@OneToMany(mappedBy = "parent")private List<Organization> children;@OneToMany(mappedBy = "organization")private List<Department> departments;private String createdAt;private String updatedAt;// Getters and setters
}
Department 实体类
import javax.persistence.*;
import java.util.List;@Entity
public class Department {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String name;private String description;private Integer employeeCount;@ManyToOne@JoinColumn(name = "organization_id")private Organization organization;@ManyToOne@JoinColumn(name = "parent_id")private Department parent;@OneToMany(mappedBy = "parent")private List<Department> children;private String createdAt;private String updatedAt;// Getters and setters
}

2.2 DTO 类设计

为了控制返回数据,我们使用 DTO(数据传输对象)来传递组织和部门的完整信息。

OrganizationDTO
import java.util.List;public class OrganizationDTO {private Long id;private String name;private String description;private String location;private String createdAt;private String updatedAt;private List<DepartmentDTO> departments;private List<OrganizationDTO> children;private OrganizationDetails details;public static class OrganizationDetails {private Long id;private String name;private String description;private String location;private String createdAt;private String updatedAt;}// Getters and setters
}
DepartmentDTO
import java.util.List;public class DepartmentDTO {private Long id;private String name;private String description;private Integer employeeCount;private String createdAt;private String updatedAt;private List<DepartmentDTO> children;private DepartmentDetails details;public static class DepartmentDetails {private Long id;private String name;private String description;private Integer employeeCount;private String createdAt;private String updatedAt;}// Getters and setters
}

2.3 Service 层设计

在 Service 层中,我们将组织和部门信息转换为树形结构,并填充每个节点的详细信息。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.List;
import java.util.stream.Collectors;@Service
public class OrganizationService {@Autowiredprivate OrganizationRepository organizationRepository;@Autowiredprivate DepartmentRepository departmentRepository;// 获取组织树形结构public List<OrganizationDTO> getOrganizationTree() {List<Organization> rootOrganizations = organizationRepository.findByParentIsNull();return rootOrganizations.stream().map(this::convertToOrganizationDTO).collect(Collectors.toList());}// 转换组织实体为组织DTOprivate OrganizationDTO convertToOrganizationDTO(Organization org) {OrganizationDTO orgDTO = new OrganizationDTO();orgDTO.setId(org.getId());orgDTO.setName(org.getName());orgDTO.setDescription(org.getDescription());orgDTO.setLocation(org.getLocation());orgDTO.setCreatedAt(org.getCreatedAt());orgDTO.setUpdatedAt(org.getUpdatedAt());// 填充子组织List<OrganizationDTO> children = org.getChildren().stream().map(this::convertToOrganizationDTO).collect(Collectors.toList());orgDTO.setChildren(children);// 填充部门树List<DepartmentDTO> departments = org.getDepartments().stream().map(this::convertToDepartmentDTO).collect(Collectors.toList());orgDTO.setDepartments(departments);// 填充详细信息OrganizationDTO.OrganizationDetails details = new OrganizationDTO.OrganizationDetails();details.setId(org.getId());details.setName(org.getName());details.setDescription(org.getDescription());details.setLocation(org.getLocation());details.setCreatedAt(org.getCreatedAt());details.setUpdatedAt(org.getUpdatedAt());orgDTO.setDetails(details);return orgDTO;}// 转换部门实体为部门DTOprivate DepartmentDTO convertToDepartmentDTO(Department dep) {DepartmentDTO depDTO = new DepartmentDTO();depDTO.setId(dep.getId());depDTO.setName(dep.getName());depDTO.setDescription(dep.getDescription());depDTO.setEmployeeCount(dep.getEmployeeCount());depDTO.setCreatedAt(dep.getCreatedAt());depDTO.setUpdatedAt(dep.getUpdatedAt());// 填充子部门List<DepartmentDTO> children = dep.getChildren().stream().map(this::convertToDepartmentDTO).collect(Collectors.toList());depDTO.setChildren(children);// 填充详细信息DepartmentDTO.DepartmentDetails details = new DepartmentDTO.DepartmentDetails();details.setId(dep.getId());details.setName(dep.getName());details.setDescription(dep.getDescription());details.setEmployeeCount(dep.getEmployeeCount());details.setCreatedAt(dep.getCreatedAt());details.setUpdatedAt(dep.getUpdatedAt());depDTO.setDetails(details);return depDTO;}
}

2.4 Controller 层设计

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.List;@RestController
@RequestMapping("/api/organizations")
public class OrganizationController {@Autowiredprivate OrganizationService organizationService;@GetMapping("/tree")public List<OrganizationDTO> getOrganizationTree() {return organizationService.getOrganizationTree();}
}

三、前端请求与展示

前端通过 GET /api/organizations/tree 请求接口,返回数据结构如下(嵌套完整组织部门信息):

[{"id": 1,"name": "总公司","description": "总部组织","location": "上海","createdAt": "2023-01-01T10:00:00","updatedAt": "2023-10-01T10:00:00","children": [{"id": 2,"name": "分公司A","description": "分公司A","location": "北京","createdAt": "2023-01-05T12:00:00","updatedAt": "2023-10-01T12:00:00","children": [],"departments": [{"id": 4,"name": "IT部","description": "技术支持部门","employeeCount": 10,"createdAt": "2023-01-10T09:00:00","updatedAt": "2023-10-01T09:00:00","children": [],"details": {"id": 4,"name": "IT部","description": "技术支持部门","employeeCount": 10,"createdAt": "2023-01-10T09:00:00","updatedAt": "2023-10-01T09:00:00"}}]}],"departments": [{"id": 1,"name": "总部","description": "总部部门","employeeCount": 20,"createdAt": "2023-01-01T10:00:00","updatedAt": "2023-10-01T10:00:00","children": [],"details": {"id": 1,"name": "总部","description": "总部部门","employeeCount": 20,"createdAt": "2023-01-01T10:00:00","updatedAt": "2023-10-01T10:00:00"}}]}
]

总结

在本文中,我们介绍了如何在 Spring Boot 中设计组织和部门表,如何处理树形结构,并通过 DTO 设计将组织和部门的完整信息传递给前端。在后端,我们使用了递归方法来构建树形数据结构,确保每个节点都包含该组织或部门的详细信息。


http://www.lryc.cn/news/619738.html

相关文章:

  • 大致计算服务器磁盘使用情况脚本
  • GNhao/GN号,海外SIM号怎么获取的步骤指南
  • npm install 的作用
  • Android实现Glide/Coil样式图/视频加载框架,Kotlin
  • 【KO】Android 网络相关面试题
  • 华为 HCIE 大数据认证中 Linux 命令行的运用及价值
  • 安装Win10怎样跳过欢迎界面
  • 数字货币的去中心化:重构价值交换的底层逻辑​
  • uniapp微信小程序-登录页面验证码的实现(springboot+vue前后端分离)EasyCaptcha验证码 超详细
  • Lombok插件介绍及安装(Eclipse)
  • Python3解释器深度解析与实战教程:从源码到性能优化的全路径探索
  • Day51--图论--99. 岛屿数量(卡码网),100. 岛屿的最大面积(卡码网)
  • 【数据结构】——栈(Stack)的原理与实现
  • 最新Coze(扣子)智能体工作流:用Coze实现「图片生成-视频制作」全自动化,3分钟批量产出爆款内容
  • 自由学习记录(83)
  • 【Unity开发】Unity核心学习(一)
  • 简单了解:CS5803芯片技术解析:HDMI到V-by-One的信号转换
  • BGP特性笔记
  • Cursor替代品:亚马逊出品,Kiro免费使用Claude Sonnet4.0一款更注重流程感的 AI IDE
  • PG靶机 - PayDay
  • lowbit函数
  • 打靶日常-文件上传
  • 《Power Voronoi图的数学原理》
  • latex 中将新的一个section重新从1开始排序,而不是和前面的section继续排序
  • PHP Word 批注处理工程设计方案(基于 `docx` 模板 + 批注驱动)
  • 【Word VBA Zotero 引用宏错误分析与改正指南】【解决[21–23]参考文献格式插入超链接问题】
  • [AI React Web] E2B沙箱 | WebGPU | 组件树 | 智能重构 | 架构异味检测
  • Navicat 询问 AI | 优化 SQL 查询
  • 打造专属 React 脚手架:从 0 到 1 开发 CLI 工具
  • Redis中灵活结合SET和SETEX的方法及多语言工具库实现