如何在 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.pswp.cn/bicheng/93111.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/93111.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java毕业设计选题推荐 |基于SpringBoot的水产养殖管理系统 智能水产养殖监测系统 水产养殖小程序

&#x1f525;作者&#xff1a;it毕设实战小研&#x1f525; &#x1f496;简介&#xff1a;java、微信小程序、安卓&#xff1b;定制开发&#xff0c;远程调试 代码讲解&#xff0c;文档指导&#xff0c;ppt制作&#x1f496; 精彩专栏推荐订阅&#xff1a;在下方专栏&#x1…

排序概念、插入排序及希尔排序

一、排序基本概念1.就地排序&#xff1a;使用恒定的额外空间来产生输出就地排序只是在原数组空间进行排序处理&#xff0c;也就是输入的数组和得到的数组是同一个2.内部排序和外部排序&#xff1a;待排序数据可以一次性载入到内存中为内部排序&#xff0c;反之数据量过大就是外…

【排序算法】④堆排序

系列文章目录 第一篇&#xff1a;【排序算法】①直接插入排序-CSDN博客 第二篇&#xff1a;【排序算法】②希尔排序-CSDN博客 第三篇&#xff1a;【排序算法】③直接选择排序-CSDN博客 第四篇&#xff1a;【排序算法】④堆排序-CSDN博客 第五篇&#xff1a;【排序算法】⑤冒…

Android领域驱动设计与分层架构实践

引言在Android应用开发中&#xff0c;随着业务逻辑日益复杂&#xff0c;传统的MVC或简单MVP架构往往难以应对。领域驱动设计(Domain-Driven Design, DDD)结合分层架构&#xff0c;为我们提供了一种更系统化的解决方案。本文将探讨如何在Android项目中应用DDD原则与分层架构&…

Android12 Framework电话功能UI定制

文章目录简介代码中间按钮Fragment创建VideoCallFragmentFragment管理添加按键挂断电话功能相关文章简介 Android版本&#xff1a;12 芯片平台&#xff1a;展锐 如下图为通话中的UI&#xff0c;打电话出去时显示的UI与此也差不多&#xff0c;但来电时UI是不一样的 这个界面是…

高并发场景下分布式ID生成方案对比与实践指南

高并发场景下分布式ID生成方案对比与实践指南 在分布式系统中&#xff0c;唯一且全局有序的ID生成器是很多业务的底层组件。随着系统并发量不断攀升&#xff0c;如何在高并发场景下保证ID的唯一性、性能、可用性和可扩展性&#xff0c;成为后端架构师需要重点考虑的问题。本文将…

Emscripten 指南:概念与使用

Emscripten 指南&#xff1a;概念与使用 什么是 Emscripten&#xff1f; Emscripten 是一个开源的编译器工具链&#xff0c;用于将 C/C 代码编译成高效的 WebAssembly&#xff08;Wasm&#xff09;和 JavaScript。它基于 LLVM 编译器架构&#xff0c;允许开发者&#xff1a; ✅…

使用镜像网站 打开克隆 GitHub 网站仓库内容 git clone https://github.com/

GitHub 网站有时因 DNS 解析问题或网络限制&#xff0c;国内访问可能会受限。使用镜像网站打开网站 使用镜像网站&#xff1a;GitHub 有一些镜像网站&#xff0c;可替代官网访问&#xff0c;如https://hub.fastgit.org、https://gitclone.com、https://github.com.cnpmjs.org等…

Linux随记(二十二)

一、redhat6.5 从openssh5.3 升级到openssh10 - 报错处理【升级后账号密码一直错误 和 sshd dead but subsys locked】 虚拟机测试情况 - 正常&#xff1a;情况一、 升级后账号密码一直错误 情况二、 执行service sshd status出现 sshd dead but subsys locked

机器学习之TF-IDF文本关键词提取

目录 一、什么是 TF-IDF&#xff1f; 1.语料库概念理解 二、TF-IDF 的计算公式 1. 词频&#xff08;TF&#xff09; 2. 逆文档频率&#xff08;IDF&#xff09; 3. TF-IDF 值 三、关键词提取之中文分词的实现 四、TF-IDF简单案例实现 &#xff08;1&#xff09;数据集…

Flutter屏幕和字体适配(ScreenUtil)

一、简介 flutter_screenutil 是一个 Flutter 插件&#xff0c;专门用于处理屏幕适配问题。它简化了不同设备间尺寸差异的处理&#xff0c;确保你的应用在各种屏幕上都能保持良好的显示效果。开发者可以通过简单的调用来设置基于设计图尺寸的控件宽高和字体大小。 项目地址&a…

mimiconda+vscode

安装miniconda实现python包管理&#xff0c;并通过vscode进行编写python代码 miniconda简单介绍 Miniconda 是 Anaconda 公司的一个轻量级 Python 发行版本&#xff0c;它包含了最基本的包管理器 conda 和 Python 环境&#xff0c;只带最核心的组件&#xff0c;没有额外的大量科…

Windows文件时间修改指南:从手动到自动化

修改文件的时间属性可以满足多种需求。比如&#xff0c;它可以帮助整理文件&#xff0c;使得文件按照特定的时间顺序排列&#xff0c;有助于更好地管理资料。它的体积真小&#xff0c;才300多KB。能用来调整文件的创建时间、最后访问和修改时间。文件时间属性修改_NewFileTime.…

能刷java题的网站

以下是一些适合刷Java题的优质网站&#xff0c;涵盖从基础到进阶、算法面试及实战项目等多种需求&#xff1a; ​一、综合编程练习平台​ ​LeetCode​&#xff08;leetcode.com&#xff09; ​特点​&#xff1a;全球最知名的算法题库&#xff0c;含海量Java题目&#xff0c;分…

掘金数据富矿,永洪科技为山东黄金定制“数智掘金”实战营

在黄金开采的轰鸣声中&#xff0c;另一场静水深流的“掘金行动”正悄然展开。山东黄金集团&#xff0c;这个行业的巨头&#xff0c;在深挖地层宝藏的同时&#xff0c;也敏锐捕捉到数据洪流中蕴藏的价值富矿。然而&#xff0c;当海量业务数据汇聚&#xff0c;如何从中精准提炼决…

【论文阅读】BEVFormer论文解析及Temporal Self-Attention、Spatial Cross-Attention注意力机制详解及代码示例

BEVFormer: Learning Bird’s-Eye-ViewRepresentation from Multi-Camera Images via Spatiotemporal Transformers|Temporal Self-Attention、Spatial Cross-Attention注意力机制详解 BEVFormer&#xff08;Bird’s-Eye-View Former&#xff09;是一种先进的计算机视觉模型&am…

在 Ubuntu 中docker容器化操作来使用新建的 glibc-2.32

在 Ubuntu 中使用容器化操作来使用新建的 glibc-2.32,可以通过创建自定义 Docker 镜像来实现。以下是完整的解决方案: 方案 1:创建包含 glibc-2.32 的 Docker 镜像 1. 创建 Dockerfile dockerfile # 使用 Ubuntu 基础镜像 FROM ubuntu:20.04# 安装编译依赖 RUN apt-get …

GOOUUU ESP32-S3-CAM 果云科技开发板开发指南(二)(超详细!)Vscode+espidf 摄像头拍摄视频实时传输到LCD,文末附源码

书接上回&#xff0c;上一篇blog是使用esp32s3通过ov2640摄像头拍摄到一帧照片&#xff0c;并把它保存到了SD卡中&#xff0c;这第二篇就通过LCD将拍摄到的图片显示到LCD上&#xff0c;本次分享硬件使用的 ESP32-S3-CAM 果云科技开发板&#xff0c;并且使用了配套的LCD扩展板&a…

攻防世界-ics-05(远程文件执行)

一.审题大致浏览一下网页&#xff0c;发现就这边会有东西。看一下源码会不会有东西或者稍微点击一下这个页面的内容看会不会出现东西。点击了一下这个云平台设备维护中心发现url变了&#xff0c;是get的方法传page参数二.尝试漏洞类型自己这边试了sql注入发现不是&#xff0c;试…

Dell PowerEdge: Servers by generation (按代系划分的服务器)

Dell PowerEdge: Servers by generation {按代系划分的服务器}1. Table of 17th, 16th, 15th, and 14th Generation PowerEdge servers2. List of all PowerEdge server models including Type, CPU vendor, Generation, and Remote ManagementReferencesPowerEdge: Servers by…