首页 > 数据库 >mysql查询结果拼接树结构(树节点的移动)

mysql查询结果拼接树结构(树节点的移动)

时间:2022-11-22 16:46:58浏览次数:45  
标签:WEIGHT 树结构 private moveNode collect 拼接 mysql TreeSelect 节点

mysql查询结果拼接树结构(树节点的移动)

思路:单表内查询全部数据,在业务层内递归拼接树结构。

前端用的是element的Tree 树形控件:

树结构实体:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class TreeSelect implements Serializable {
    
    /**
    * 所需参数跟前端商讨,参数名跟前端确认一下,我的就是两个前端没统一后面还重加了个
    */

    private static final long serialVersionUID = -1370015781272165366L;

    private Long id;

    private Long pid;

    private String label;

    /**
    * 排序,树节点移动需要
    */
    private int sno;

    @ApiModelProperty(value = "是否启用,0禁用,1正常")
    private int status;

    /**
    * 子级,下一级节点
    */
    private List<TreeSelect> subordinate;

}

业务层拼接树:

    @Override
    public Object getSysClassifyItemTree(Long versionId) {
		//查询出全部数据
        List<TreeSelect> sysClassifyItemList = classifyMapper.getAll(versionId);

        Map<Long, List<TreeSelect>> collect = sysClassifyItemList.stream().collect(Collectors.groupingBy(TreeSelect::getPid));
        List<TreeSelect> list = collect.get(0L);
        List<TreeSelect> items = new ArrayList<>();
        if (null == list) {
            //在没有数据的时候,给前端返回一个虚拟节点方便展示,操作
            TreeSelect sss = new TreeSelect(0l, "虚拟节点", 0l);
            items.add(sss);
            return JSON.toJSON(items).toString();
        }
        for (TreeSelect sysClassifyItem : collect.get(0L)) {
            buildTree(sysClassifyItem, collect);
        }
        //如果这个树需要一个固定的父节点,new一个TreeSelect对象 f,把拼出来的树塞到f的subordinate也就是子级。
        return JSON.toJSON(list).toString();
    }

	/**
	* 拼接树
	*/
    private void buildTree(TreeSelect sysClassifyItem, Map<Long, List<TreeSelect>> collect) {
        if (null == sysClassifyItem || null == collect.get(sysClassifyItem.getId())) {
            return;
        }
        sysClassifyItem.setSubordinate(collect.get(sysClassifyItem.getId()));
        for (TreeSelect classifyItem : collect.get(sysClassifyItem.getId())) {
            buildTree(classifyItem, collect);
        }
    }

下来是树节点的移动,也就是上移下移(提出到上层节点跟插入到子级节点就不放了,单纯的修改而已)

在移动的时候我们需要知道自己的位置和要移动到的位置,也就是目标位置

移动节点实体:

@Data
public class MoveNode implements Serializable {
    private static final long serialVersionUID = 8370232720686896563L;

    private Long parentId;
    private Long sno;//排序,节点当前位置
    private Long targetSno;//目标位置
    private Long id;

}

业务层:

@Override
public boolean moveUp(MoveNode moveNode) {

    //判断节点是上移还是下移
    if (moveNode.getMoveSno() > moveNode.getSno()) {
        if (structureMapper.moveDownA(moveNode) == -1 || structureMapper.move(moveNode) == -1) {
            return false;
        }
    } else if (moveNode.getMoveSno() < moveNode.getSno()) {
        if (structureMapper.moveUpA(moveNode) == -1 || structureMapper.move(moveNode) == -1) {
            return false;
        }
    }
    return true;
}

mapper:

<!--上移我们需要以目标位置到自身位置的前一个位置为区间给每个节点的顺序都往后调一位-->
<update id="moveUpA">
    UPDATE SYS_TEAM
    <set>
        WEIGHT = WEIGHT + 1
    </set>
    <where>
        <if test="parentId != null">and UNITID = #{parentId}</if>
        <if test="moveSno != null and sno != null">and WEIGHT BETWEEN #{moveSno} and #{sno}-1</if>
    </where>
</update>

<!--下移就刚好相反,我们需要以自身位置的后一个位置到目标位置为区间给每个节点的顺序都往前调一位-->
<update id="moveDownA">
    UPDATE SYS_TEAM
    <set>
        WEIGHT = WEIGHT - 1
    </set>
    <where>
        <if test="parentId != null">and UNITID = #{parentId}</if>
        <if test="moveSno != null and sno != null">and WEIGHT BETWEEN #{sno}+1 and #{moveSno}</if>
    </where>
</update>

<!--每次移动后将自身位置替换为目标位置-->
<update id="move">
    UPDATE SYS_TEAM
    <set>
        <if test="moveSno != null">WEIGHT = #{moveSno}</if>
    </set>
    <where>
        <if test="parentId != null">and UNITID = #{parentId}</if>
        <if test="sno != null">and WEIGHT = #{sno}</if>
        <if test="id != null">and ID = #{id}</if>
    </where>
</update>

看下图,移动这里有个问题是前端无法拿到准确的位置,因为element的可拖拽树每个节点有after,before两条线,绑定的是这个节点自身的属性,也就是说两个节点之间有两条线,这就导致c节点在移动到A——B之间时可能会放到a2的这条线导致目标位置拿成了A的位置。即我本身是想将c移动到B的上方,结果是变成了A的上方,同理下移的时候A移动到B的下面,不小心就变成了C的下面。我在网上看有其他的tree控件是可以解决的,前端怕改的地方太多引起别的问题,一直没动。不知道大家有没有遇到过,怎么解决的呢?

标签:WEIGHT,树结构,private,moveNode,collect,拼接,mysql,TreeSelect,节点
From: https://www.cnblogs.com/ComfortableM/p/16915581.html

相关文章

  • MySQL 5.7.20详细安装教程(图文版)
    MySQL5.7.20详细安装教程(图文版)在自己在电脑上安装个MySQL的5.7.20版本,安装此版本主要是方便于平常使用。如图,选择自己电脑对应的版本进入官网进行下载。1、下载地址:My......
  • node 连接MySQL
    使用node创建一个服务端比java简单多,下面创建一个node服务端,连接MySQL并且将数据在浏览器显示出来一.node创建服务端案例varhttp=require("http");http.createSe......
  • MySql在windows系统以及linux系统下的忘记密码以及密码修改问题
    首先密码错误可能是由于系统的原因导致的密码重置,具体原因不明。但是不管如何,可以将密码修改为自己的密码第一步需要跳过密码验证环节,有两种做法,第一是在my.ini文件中【my......
  • MySQL-报错提示:ERROR 2002 (HY000): Can't connect to local MySQL
     场景:通过mysql -hlocalhost-uroot-p连接MySQL数据库时报错:ERROR2002(HY000):Can'tconnecttolocalMySQLserverthrough socket /tmp/mysql.sock解决......
  • 存取数据的演变史、数据库软件应用史、数据库的本质、数据库的分类、MySQL简介、MySQL
    存取数据的演变史1.文本文件 文件路径不固定:C:\aaa.txtD:\bbb.txtE:\ccc.txt 数据格式不统一:jason|123 jason$123 jason1232.软件开发目录规范 规定了数......
  • 数据库介绍及Mysql简介
    目录存取数据的演变史数据库软件应用史数据库的本质数据库的分类MySQL简介MySQL基本使用系统服务的制作密码相关操作SQL与NoSQL数据库重要概念基本SQL语句存取数据的演变......
  • 数据库理论及MySql下载
    数据库理论及MySql下载数据库发展存取数据的发展自定义文件,以各种各样的形式存储软件开发目录规范的db文件夹数据库服务:统一了存储路径和操作数据的方式降低了......
  • MySQL的概念、编译安装
    一.数据库的基本概念1、数据(Data)•描述事物的符号记录•包括数字,文字,图形,图像,声音,档案记录等•以“记录”形式按统一的格式进行存储2、表•将不同的记录组织在一......
  • 封装适用于CentOS7的MySQL离线包
    1构建一个centos7.6.1810的docker镜像,用于下载MySQL+xtrabackup所需安装包7.6.1810的docker镜像,低版本最小安装,会尽可能把所需的包拉齐。Dockerfile文件如下FROMcent......
  • Mysql索引
    Innodb页结构在插入数据到用户数据区域时会进行排序页目录分组存储数据区域每一组的第一个元素索引值和地址,每组默认为6个元素......