java框架树结构实现(带层级、编码、排序)

2024-06-06 14:04

本文主要是介绍java框架树结构实现(带层级、编码、排序),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1、需求

实现一个影像资料库的功能,用树结构对资料进行分类

2、数据结构

通过id、pid表示父子关系

通过code表示层级关系

通过layer表示层级

通过sort进行排序

3、实体类

package org.jeecg.modules.image.entity;import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import org.jeecg.common.system.base.entity.BaseSearchDTO;
import org.jeecg.common.system.base.support.Condition;
import org.jeecg.common.system.base.support.Match;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.springframework.data.annotation.Transient;
import org.springframework.format.annotation.DateTimeFormat;import java.util.ArrayList;
import java.util.Date;
import java.util.List;/*** @Description: 影像资料分类* @Author: jeecg-boot* @Date: 2024-05-28* @Version: V1.0*/
@Data
@TableName("img_classification")
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
@ApiModel(value = "img_classification对象", description = "影像资料分类")
public class ImgClassification extends BaseSearchDTO {/*** 主键*/@TableId(type = IdType.ASSIGN_ID)@ApiModelProperty(value = "主键")private String id;/*** 创建人*/@ApiModelProperty(value = "创建人")private String createBy;/*** 创建日期*/@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")@ApiModelProperty(value = "创建日期")private Date createTime;/*** 更新人*/@ApiModelProperty(value = "更新人")private String updateBy;/*** 更新日期*/@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")@ApiModelProperty(value = "更新日期")private Date updateTime;/*** 所属部门*/@ApiModelProperty(value = "所属部门")private String sysOrgCode;/*** 父id*/@Excel(name = "父id", width = 15)@ApiModelProperty(value = "父id")private String pid;/*** 分类编码*/@Excel(name = "分类编码", width = 15)@ApiModelProperty(value = "分类编码")@Condition(match = Match.LLIKE)private String code;/*** 分类名称*/@Excel(name = "分类名称", width = 15)@ApiModelProperty(value = "分类名称")@Condition(match = Match.LIKE)private String name;/*** 层级*/@Excel(name = "层级", width = 15)@ApiModelProperty(value = "层级")private Integer layer;/*** 排序*/@Excel(name = "排序", width = 15)@ApiModelProperty(value = "排序")private Integer sort;/*** 是否有子节点*/@Excel(name = "是否有子节点", width = 15)@ApiModelProperty(value = "是否有子节点")private Boolean hasChildren;不在库里/*** 父级名称*/@TableField(exist = false)@ApiModelProperty(value = "父级名称")private String parentName;/*** 子集*/@Transient@TableField(exist = false)@ApiModelProperty(value = "子集")private List<ImgClassification> children = new ArrayList<>();}

4、控制器

package org.jeecg.modules.image.controller;import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.common.system.base.service.BaseService;
import org.jeecg.modules.image.entity.ImgClassification;
import org.jeecg.modules.image.service.IImgClassificationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;/*** @Description: 影像资料分类* @Author: jeecg-boot* @Date: 2024-05-28* @Version: V1.0*/
@Api(tags = "1.0.1.0 影像资料分类")
@RestController
@RequestMapping("/image/imgClassification")
@Slf4j
public class ImgClassificationController extends JeecgController<ImgClassification, IImgClassificationService> {@Autowiredprivate IImgClassificationService imgClassificationService;@Autowiredprivate BaseService<ImgClassification> baseService;//    /**
//     * 分页列表查询
//     *
//     * @param imgClassification
//     * @param pageNo
//     * @param pageSize
//     * @param req
//     * @return
//     */
//    //@AutoLog(value = "影像资料分类-分页列表查询")
//    @ApiOperation(value = "影像资料分类-分页列表查询", notes = "影像资料分类-分页列表查询")
//    @GetMapping(value = "/list")
//    public Result<IPage<ImgClassification>> queryPageList(ImgClassification imgClassification,
//                                                          @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
//                                                          @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
//                                                          HttpServletRequest req) {
//        QueryWrapper<ImgClassification> queryWrapper = QueryGenerator.initQueryWrapper(imgClassification, req.getParameterMap());
//        Page<ImgClassification> page = new Page<ImgClassification>(pageNo, pageSize);
//        IPage<ImgClassification> pageList = imgClassificationService.page(page, queryWrapper);
//        return Result.OK(pageList);
//    }/*** 分页列表查询** @param imgClassification* @return*///@AutoLog(value = "影像资料分类-分页列表查询")@ApiOperation(value = "影像资料分类-分页列表查询", notes = "影像资料分类-分页列表查询")@GetMapping(value = "/list")public Result<IPage<ImgClassification>> queryPageList(ImgClassification imgClassification) {IPage<ImgClassification> pageList = baseService.selectPageByDTO(imgClassification);return Result.OK(pageList);}/*** 列表查询** @param imgClassification* @return*/@ApiOperation(value = "影像资料分类-列表查询", notes = "影像资料分类-列表查询")@GetMapping(value = "/listAll")public Result<List<ImgClassification>> listAll(ImgClassification imgClassification) {List<ImgClassification> list = baseService.selectlistByDto(imgClassification);return Result.OK(list);}/*** 添加** @param imgClassification* @return*/@AutoLog(value = "影像资料分类-添加")@ApiOperation(value = "影像资料分类-添加", notes = "影像资料分类-添加")//@RequiresPermissions("image:img_classification:add")@PostMapping(value = "/add")public Result<String> add(@RequestBody ImgClassification imgClassification) {
//        imgClassificationService.save(imgClassification);imgClassificationService.add(imgClassification);return Result.OK("添加成功!");}/*** 批量添加** @param imgClassifications* @return*/@AutoLog(value = "影像资料分类-批量添加")@ApiOperation(value = "影像资料分类-批量添加", notes = "影像资料分类-批量添加")@PostMapping(value = "/addBatch")public Result<String> addBatch(@RequestBody List<ImgClassification> imgClassifications) {
//        imgClassificationService.save(imgClassification);imgClassificationService.addBatch(imgClassifications);return Result.OK("添加成功!");}/*** 编辑** @param imgClassification* @return*/@AutoLog(value = "影像资料分类-编辑")@ApiOperation(value = "影像资料分类-编辑", notes = "影像资料分类-编辑")//@RequiresPermissions("image:img_classification:edit")@RequestMapping(value = "/edit", method = {RequestMethod.PUT, RequestMethod.POST})public Result<String> edit(@RequestBody ImgClassification imgClassification) {imgClassificationService.updateById(imgClassification);return Result.OK("编辑成功!");}/*** 通过id删除** @param id* @return*/@AutoLog(value = "影像资料分类-通过id删除")@ApiOperation(value = "影像资料分类-通过id删除", notes = "影像资料分类-通过id删除")//@RequiresPermissions("image:img_classification:delete")@DeleteMapping(value = "/delete")public Result<String> delete(@RequestParam(name = "id", required = true) String id) {
//        imgClassificationService.removeById(id);imgClassificationService.delete(id);return Result.OK("删除成功!");}/*** 批量删除** @param ids* @return*/@AutoLog(value = "影像资料分类-批量删除")@ApiOperation(value = "影像资料分类-批量删除", notes = "影像资料分类-批量删除")//@RequiresPermissions("image:img_classification:deleteBatch")@DeleteMapping(value = "/deleteBatch")public Result<String> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
//        this.imgClassificationService.removeByIds(Arrays.asList(ids.split(",")));imgClassificationService.deleteBatch(ids);return Result.OK("批量删除成功!");}/*** 通过id查询** @param id* @return*///@AutoLog(value = "影像资料分类-通过id查询")@ApiOperation(value = "影像资料分类-通过id查询", notes = "影像资料分类-通过id查询")@GetMapping(value = "/queryById")public Result<ImgClassification> queryById(@RequestParam(name = "id", required = true) String id) {
//        ImgClassification imgClassification = imgClassificationService.getById(id);ImgClassification imgClassification = imgClassificationService.queryById(id);if (imgClassification == null) {return Result.error("未找到对应数据");}return Result.OK(imgClassification);}/*** 导出excel** @param request* @param imgClassification*///@RequiresPermissions("image:img_classification:exportXls")@RequestMapping(value = "/exportXls")public ModelAndView exportXls(HttpServletRequest request, ImgClassification imgClassification) {return super.exportXls(request, imgClassification, ImgClassification.class, "影像资料分类");}/*** 通过excel导入数据** @param request* @param response* @return*///@RequiresPermissions("image:img_classification:importExcel")@RequestMapping(value = "/importExcel", method = RequestMethod.POST)public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {return super.importExcel(request, response, ImgClassification.class);}/*** 获取树结构** @param dto* @return*/@PostMapping("/getTree")@ApiOperation(value = "获取树结构")public Result<?> getTree(@ApiParam(value = "查询条件")@RequestBody ImgClassification dto) {List<ImgClassification> tree = imgClassificationService.getTree(dto);return Result.OK(tree);}/*** 设置innercode码*/@ApiOperation(value = "设置innercode码", notes = "设置innercode码")@GetMapping(value = "/initCode")public Result<?> initCode() {imgClassificationService.initCode();return Result.OK("处理完成");}}

5、service层

package org.jeecg.modules.image.service;import com.baomidou.mybatisplus.extension.service.IService;
import org.jeecg.modules.image.entity.ImgClassification;import java.util.List;/*** @Description: 影像资料分类* @Author: jeecg-boot* @Date: 2024-05-28* @Version: V1.0*/
public interface IImgClassificationService extends IService<ImgClassification> {List<ImgClassification> selectTree(ImgClassification dto);List<ImgClassification> getTree(ImgClassification dto);void initCode();void add(ImgClassification imgClassification);void delete(String id);void addBatch(List<ImgClassification> imgClassifications);void deleteBatch(String ids);ImgClassification queryById(String id);
}

package org.jeecg.modules.image.service.impl;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.jeecg.common.exception.BusinessException;
import org.jeecg.common.system.base.service.BaseService;
import org.jeecg.common.util.StringUtil;
import org.jeecg.modules.image.entity.ImgClassification;
import org.jeecg.modules.image.entity.ImgLibrary;
import org.jeecg.modules.image.mapper.ImgClassificationMapper;
import org.jeecg.modules.image.service.IImgClassificationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;/*** @Description: 影像资料分类* @Author: jeecg-boot* @Date: 2024-05-28* @Version: V1.0*/
@Service
public class ImgClassificationServiceImpl extends ServiceImpl<ImgClassificationMapper, ImgClassification> implements IImgClassificationService {@ResourceImgClassificationMapper mapper;@Autowiredprivate BaseService<ImgClassification> baseService;@Autowiredprivate BaseService<ImgLibrary> imgLibraryService;@Overridepublic List<ImgClassification> selectTree(ImgClassification dto) {return mapper.selectTree(dto);}@Overridepublic List<ImgClassification> getTree(ImgClassification dto) {List<ImgClassification> returndemo = this.selectTree(dto);List<ImgClassification> tree = Collections.synchronizedList(new ArrayList<>());String id = "1";if (StringUtil.isNotEmpty(dto.getId())) {id = dto.getId();}if (StringUtil.isNotEmpty(returndemo)) {String finalId = id;returndemo.parallelStream().forEach(x -> {if (finalId.equals(x.getId())) {//现在做全局递归,之后更改tree.add(findChildren(x, returndemo));}});}//根据日期进行升序排序for (ImgClassification e : tree) {e.setChildren(sort(e.getChildren()));}List<ImgClassification> treeAsce = sort(tree);return treeAsce;}private List<ImgClassification> sort(List<ImgClassification> source) {List<ImgClassification> treeAsce= source.stream().sorted(Comparator.comparing(ImgClassification::getSort)).collect(Collectors.toList());for (ImgClassification e : source) {if (e.getChildren().size() > 0) {e.setChildren(sort(e.getChildren()));}}return treeAsce;}/*** @param node  .* @param lists .* @return .*/private static ImgClassification findChildren(ImgClassification node, List<ImgClassification> lists) {lists.parallelStream().forEach(y -> {if (node.getId().equals(y.getPid())) {if (node.getChildren() == null) {node.setChildren(new ArrayList<ImgClassification>());}node.getChildren().add(findChildren(y, lists));}});return node;}@Overridepublic void initCode() {ImgClassification dto = new ImgClassification();List<ImgClassification> treeList = getTree(dto);dealInnerCode(treeList, true);}@Overridepublic void addBatch(List<ImgClassification> imgClassifications) {for (ImgClassification imgClassification : imgClassifications) {this.add(imgClassification);}}@Overridepublic void add(ImgClassification imgClassification) {//更新父节点的hasChildrenImgClassification parent = this.queryById(imgClassification.getPid());if (StringUtil.isEmpty(parent)) {throw new BusinessException("未找到父节点");}parent.setHasChildren(true);this.updateById(parent);//更新本节点的层级、编码、排序imgClassification = this.reDoEntity(parent, imgClassification);//新增this.save(imgClassification);}/*** 获取分类的 层级layer、 编码code、 排序sort*/private ImgClassification reDoEntity(ImgClassification parent, ImgClassification imgClassification) {String code = null;//当前父节点有几个子节点List<ImgClassification> childrenList = parent.getChildren();int lastNumber = 1;if (StringUtil.isEmpty(childrenList)) {// 列表为空或null,处理这种情况code = parent.getCode() + "-1";} else {//查询父节点下最新的一条记录ImgClassification latestItem = childrenList.get(0); // 假设第一个元素是最新的String latestCode = latestItem.getCode();// 按 "-" 分割字符串String[] parts = latestCode.split("-");// 检查是否至少有一个部分if (parts.length == 0) {System.out.println("没有分隔符,找不到数值");}// 找到最后一个编号,并转换为整数lastNumber = Integer.parseInt(parts[parts.length - 1]);// 将最后一个编号加1lastNumber++;// 将加1后的整数转换回字符串String lastNumberStr = String.valueOf(lastNumber);// 替换原来的最后一个编号,并用 "-" 重新连接所有编号// 如果只有一个部分,则不需要"-"StringBuilder newS = new StringBuilder();for (int i = 0; i < parts.length - 1; i++) {newS.append(parts[i]).append("-");}newS.append(lastNumberStr);code = newS.toString();}imgClassification.setCode(code);imgClassification.setLayer(parent.getLayer() + 1);if (StringUtil.isEmpty(imgClassification.getSort())) {imgClassification.setSort(lastNumber + 1);}//更新本节点的hasChildrenimgClassification.setHasChildren(false);return imgClassification;}@Overridepublic void deleteBatch(String ids) {List<String> idList = Arrays.asList(ids.split(","));if (StringUtil.isNotEmpty(idList)) {for (String id : idList) {this.delete(id);}}}@Overridepublic ImgClassification queryById(String id) {ImgClassification imgClassification = this.getById(id);//获取子节点ImgClassification dto = new ImgClassification();dto.setPid(id);dto.setOrderby("create_time desc");List<ImgClassification> childrenList = baseService.selectlistByDto(dto);imgClassification.setChildren(childrenList);return imgClassification;}/*** 删除分类* 1.根节点不允许删除* 2.节点下挂了资料,不能删除* 3.更新父节点的hasChildren* 4.删除本节点** @param id*/@Overridepublic void delete(String id) {ImgClassification imgClassification = this.getById(id);//根节点不允许删除if (id.equals("1")) {throw new BusinessException("根节点不允许删除。");}//判断分类下是否有资料,如果有,则不能删除if (hasData(imgClassification)) {throw new BusinessException(imgClassification.getName() + "分类下存在资料,不能删除。" + imgClassification.getCode() + ":" + imgClassification.getId());}//更新父节点的hasChildrenif (imgClassification != null) {     //如果删除的是顶级节点,则父节点的hasChildren置为falseImgClassification parent = this.queryById(imgClassification.getPid());if (parent != null) {List<ImgClassification> childrenList = parent.getChildren();if (StringUtil.isNotEmpty(childrenList) && childrenList.size() == 1) {parent.setHasChildren(false);this.updateById(parent);}}}//删除本节点this.removeById(id);}private Boolean hasData(ImgClassification imgClassification) {ImgLibrary dto = new ImgLibrary();dto.setClsCode(imgClassification.getCode());List<ImgLibrary> imgLibraryList = imgLibraryService.selectlistByDto(dto);if (imgLibraryList != null && !imgLibraryList.isEmpty()) {return true;}return false;}public void dealInnerCode(List<ImgClassification> treeList, Boolean isTop) {for (int i = 0; i < treeList.size(); i++) {String thisId = treeList.get(i).getId();String pId = treeList.get(i).getPid();ImgClassification imgClassification = this.getById(thisId);if (isTop) {imgClassification.setCode("0");} else {imgClassification.setCode(getCodeById(pId) + (i + 1));}//更新this.updateById(imgClassification);List<ImgClassification> childrenList = treeList.get(i).getChildren();if (StringUtil.isNotEmpty(childrenList)) {dealInnerCode(childrenList, false);}}}public String getCodeById(String id) {ImgClassification imgClassification = this.getById(id);return imgClassification.getCode();}
}

6、dao层

package org.jeecg.modules.image.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import org.jeecg.modules.image.entity.ImgClassification;import java.util.List;/*** @Description: 影像资料分类* @Author: jeecg-boot* @Date: 2024-05-28* @Version: V1.0*/
public interface ImgClassificationMapper extends BaseMapper<ImgClassification> {List<ImgClassification> selectTree(@Param("dto") ImgClassification dto);
}

7、xml层

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.jeecg.modules.image.mapper.ImgClassificationMapper"><!-- 树结构-查父节点的名字 --><select id="selectTree"parameterType="Object"resultType="org.jeecg.modules.image.entity.ImgClassification">SELECT t1.name AS parent_name,t.*FROM IMG_CLASSIFICATION tLEFT JOIN IMG_CLASSIFICATION t1 ON t.pid = t1.idWHERE 1 = 1<if test="dto.name !=null and dto.name != ''">AND t.name like concat(concat('%',#{dto.name}),'%')</if>ORDER BYt1.CREATE_TIME,t.CREATE_TIME</select></mapper>

这篇关于java框架树结构实现(带层级、编码、排序)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1036311

相关文章

使用Python实现IP地址和端口状态检测与监控

《使用Python实现IP地址和端口状态检测与监控》在网络运维和服务器管理中,IP地址和端口的可用性监控是保障业务连续性的基础需求,本文将带你用Python从零打造一个高可用IP监控系统,感兴趣的小伙... 目录概述:为什么需要IP监控系统使用步骤说明1. 环境准备2. 系统部署3. 核心功能配置系统效果展

解决IDEA报错:编码GBK的不可映射字符问题

《解决IDEA报错:编码GBK的不可映射字符问题》:本文主要介绍解决IDEA报错:编码GBK的不可映射字符问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录IDEA报错:编码GBK的不可映射字符终端软件问题描述原因分析解决方案方法1:将命令改为方法2:右下jav

Java 实用工具类Spring 的 AnnotationUtils详解

《Java实用工具类Spring的AnnotationUtils详解》Spring框架提供了一个强大的注解工具类org.springframework.core.annotation.Annot... 目录前言一、AnnotationUtils 的常用方法二、常见应用场景三、与 JDK 原生注解 API 的

Java controller接口出入参时间序列化转换操作方法(两种)

《Javacontroller接口出入参时间序列化转换操作方法(两种)》:本文主要介绍Javacontroller接口出入参时间序列化转换操作方法,本文给大家列举两种简单方法,感兴趣的朋友一起看... 目录方式一、使用注解方式二、统一配置场景:在controller编写的接口,在前后端交互过程中一般都会涉及

Java中的StringBuilder之如何高效构建字符串

《Java中的StringBuilder之如何高效构建字符串》本文将深入浅出地介绍StringBuilder的使用方法、性能优势以及相关字符串处理技术,结合代码示例帮助读者更好地理解和应用,希望对大家... 目录关键点什么是 StringBuilder?为什么需要 StringBuilder?如何使用 St

Python实现微信自动锁定工具

《Python实现微信自动锁定工具》在数字化办公时代,微信已成为职场沟通的重要工具,但临时离开时忘记锁屏可能导致敏感信息泄露,下面我们就来看看如何使用Python打造一个微信自动锁定工具吧... 目录引言:当微信隐私遇到自动化守护效果展示核心功能全景图技术亮点深度解析1. 无操作检测引擎2. 微信路径智能获

使用Java将各种数据写入Excel表格的操作示例

《使用Java将各种数据写入Excel表格的操作示例》在数据处理与管理领域,Excel凭借其强大的功能和广泛的应用,成为了数据存储与展示的重要工具,在Java开发过程中,常常需要将不同类型的数据,本文... 目录前言安装免费Java库1. 写入文本、或数值到 Excel单元格2. 写入数组到 Excel表格

Java并发编程之如何优雅关闭钩子Shutdown Hook

《Java并发编程之如何优雅关闭钩子ShutdownHook》这篇文章主要为大家详细介绍了Java如何实现优雅关闭钩子ShutdownHook,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起... 目录关闭钩子简介关闭钩子应用场景数据库连接实战演示使用关闭钩子的注意事项开源框架中的关闭钩子机制1.

Python中pywin32 常用窗口操作的实现

《Python中pywin32常用窗口操作的实现》本文主要介绍了Python中pywin32常用窗口操作的实现,pywin32主要的作用是供Python开发者快速调用WindowsAPI的一个... 目录获取窗口句柄获取最前端窗口句柄获取指定坐标处的窗口根据窗口的完整标题匹配获取句柄根据窗口的类别匹配获取句

Maven中引入 springboot 相关依赖的方式(最新推荐)

《Maven中引入springboot相关依赖的方式(最新推荐)》:本文主要介绍Maven中引入springboot相关依赖的方式(最新推荐),本文给大家介绍的非常详细,对大家的学习或工作具有... 目录Maven中引入 springboot 相关依赖的方式1. 不使用版本管理(不推荐)2、使用版本管理(推