【202】Java8从数据库表中读取树形结构示例

数据库准备工作

数据库表结构如下:

CREATE TABLE `t_menu` (
  `c_id` varchar(80) NOT NULL COMMENT '主键',
  `c_name` varchar(15) NOT NULL COMMENT '菜单名称',
  `c_parent_id` varchar(80) NOT NULL COMMENT '父级菜单id',
  `c_icon` text COMMENT '图标',
  `c_type` tinyint(1) NOT NULL COMMENT '类型,字段menu_type',
  `c_create_id` varchar(80) NOT NULL COMMENT '创建者ID',
  `c_create_time` timestamp NOT NULL COMMENT '创建时间',
  `c_update_id` varchar(80) NOT NULL COMMENT '更新者ID',
  `c_update_time` timestamp NOT NULL COMMENT '更新时间',
  `c_no` int(10) DEFAULT NULL COMMENT '顺序',
  `c_del_flag` tinyint(1) NOT NULL COMMENT '是否删除',
  PRIMARY KEY (`c_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='菜单'

插入数据:


INSERT INTO `t_menu` (
  `c_id`, `c_name`,
  `c_parent_id`, `c_icon`,
  `c_type`, `c_create_id`, `c_create_time`,
  `c_update_id`, `c_update_time`, `c_no`, `c_del_flag`
) 
VALUES
  (
    '0_0_01ec9a90f6b34439bb979e4fad37852b','百叶箱数据',
    '0_0_61379d8d12b3456797188a9044d14f3c',NULL, 2,
    '0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-18 22:43:30',
    '0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-18 22:43:30', 1,0
  ),
  (
    '0_0_090d3da1301841f6b43e3a3ff2b44f68', '删除',
    '0_0_c982f477026541848405484f08ff1dfa', NULL, 2,
    '0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-20 11:04:09',
    '0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-20 11:07:34', 3, 0
  ),
  (
    '0_0_0ab19e321a5f490e9015f6e4cd496d27','分配菜单',
    '0_0_e7b9049e8ad34a78af90286b63f4759c', NULL, 3,
    '0_0_4c7b563b83fc410c957d08403b9e25ff','2024-03-19 10:08:44',
    '0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-19 10:08:44',4, 0
  ),
  (
    '0_0_3983284d54104f359b8406a50fa45632','4444',
    '0_0_f887ea1dc38341559285926c54123516', NULL, 3,
    '0_0_4c7b563b83fc410c957d08403b9e25ff','2024-03-22 11:00:16',
    '0_0_4c7b563b83fc410c957d08403b9e25ff','2024-03-22 11:00:16', 1, 0
  ),
  (
    '0_0_3de80520f6f74b2386b8381a564c4e09', '删除',
    '0_0_99cad34fd9814ff4a8c88e72d60a552d', NULL, 3,
    '0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-19 09:54:43',
    '0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-19 09:54:43', 3, 0
  ),
  (
    '0_0_545fb128881f462f8bc828b54e19e034',
    '删除', '0_0_da9e85f955f44e16bfa8a20659de30d7', NULL, 3,
    '0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-19 09:38:27',
    '0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-19 09:38:27', 3, 0
  ),
  (
    '0_0_61379d8d12b3456797188a9044d14f3c', '智慧农业', '-1', NULL, 1,
    '0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-18 21:31:47', 
    '0_0_4c7b563b83fc410c957d08403b9e25ff','2024-03-18 21:31:47', 2, 0
  ),
  (
    '0_0_634317d8797e4aacb467e348a1ac8924','添加',
    '0_0_c982f477026541848405484f08ff1dfa', NULL, 2,
    '0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-20 11:03:33',
    '0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-20 11:06:46', 1,0
  ),
  (
    '0_0_661824d0f33441aba8236d5be366434f','系统管理','-1', NULL, 1,
    '0_0_4c7b563b83fc410c957d08403b9e25ff','2024-03-18 21:02:49',
    '0_0_4c7b563b83fc410c957d08403b9e25ff','2024-03-18 21:02:49',1,0
  ),
  (
    '0_0_6a71439c4de84eb19f99648df760c9c0','修改',
    '0_0_e7b9049e8ad34a78af90286b63f4759c',NULL,3,
    '0_0_4c7b563b83fc410c957d08403b9e25ff','2024-03-19 10:08:21',
    '0_0_4c7b563b83fc410c957d08403b9e25ff','2024-03-19 10:08:21',2,0
  ),
  (
    '0_0_729b70ba39144dbb930547d39e4700b0', '添加',
    '0_0_e7b9049e8ad34a78af90286b63f4759c', NULL, 3,
    '0_0_4c7b563b83fc410c957d08403b9e25ff','2024-03-19 10:08:13',
    '0_0_4c7b563b83fc410c957d08403b9e25ff','2024-03-19 10:08:13',1, 0
  ),
  (
    '0_0_843138ca616b466b8904c53c31b1bd2e','添加',
    '0_0_da9e85f955f44e16bfa8a20659de30d7',NULL,3,
    '0_0_4c7b563b83fc410c957d08403b9e25ff','2024-03-19 09:38:10',
    '0_0_4c7b563b83fc410c957d08403b9e25ff','2024-03-19 09:38:10',1,0
  ),
  (
    '0_0_99cad34fd9814ff4a8c88e72d60a552d', '用户管理',
    '0_0_661824d0f33441aba8236d5be366434f', NULL, 2,
    '0_0_4c7b563b83fc410c957d08403b9e25ff','2024-03-18 21:04:43',
    '0_0_4c7b563b83fc410c957d08403b9e25ff','2024-03-18 21:04:43', 1,0
  ),
  (
    '0_0_a3486bd0026f47c298b5d2d55db6f733', '重置密码',
    '0_0_99cad34fd9814ff4a8c88e72d60a552d', NULL, 3,
    '0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-19 09:54:58',
    '0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-19 09:54:58', 4, 0
  ),
  (
    '0_0_a695d1d7a5c243379ceae6560855496e', '删除',
    '0_0_e7b9049e8ad34a78af90286b63f4759c', NULL, 3,
    '0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-19 10:08:28',
    '0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-19 10:08:28',3, 0
  ),
  (
    '0_0_a88b254640f94f3c9afab62ef10dbedb', '分配角色',
    '0_0_99cad34fd9814ff4a8c88e72d60a552d',  NULL, 3,
    '0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-19 09:55:20',
    '0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-19 09:55:20', 5, 0
  ),
  (
    '0_0_acf36bbee31541ad874af0b78de92ff5', '删除',
    '0_0_01ec9a90f6b34439bb979e4fad37852b', NULL, 3,
    '0_0_4c7b563b83fc410c957d08403b9e25ff','2024-03-19 09:35:33',
    '0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-19 09:35:33', 1,0
  ),
  (
    '0_0_bf244c78e686400db9808cd5fb0c3c91','修改',
    '0_0_c982f477026541848405484f08ff1dfa', NULL,2,
    '0_0_4c7b563b83fc410c957d08403b9e25ff','2024-03-20 11:04:02',
    '0_0_4c7b563b83fc410c957d08403b9e25ff','2024-03-20 11:07:19', 2,0
  ),
  (
    '0_0_c8085841164547a5834d51eb7d3f566f','修改',
    '0_0_99cad34fd9814ff4a8c88e72d60a552d', NULL,3,
    '0_0_4c7b563b83fc410c957d08403b9e25ff','2024-03-19 09:54:34',
    '0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-19 09:54:34',2,0
  ),
  (
    '0_0_c982f477026541848405484f08ff1dfa','接口权限',
    '0_0_661824d0f33441aba8236d5be366434f', NULL, 2,
    '0_0_4c7b563b83fc410c957d08403b9e25ff','2024-03-18 21:16:20',
    '0_0_4c7b563b83fc410c957d08403b9e25ff','2024-03-20 10:58:32', 4,0
  ),
  (
    '0_0_d00f45f79a1941ad9adc0567352e6670', '修改',
    '0_0_da9e85f955f44e16bfa8a20659de30d7', NULL, 3,
    '0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-19 09:38:18',
    '0_0_4c7b563b83fc410c957d08403b9e25ff','2024-03-19 09:38:18', 2, 0
  ),
  (
    '0_0_da9e85f955f44e16bfa8a20659de30d7', '菜单管理',
    '0_0_661824d0f33441aba8236d5be366434f', NULL, 2,
    '0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-18 21:05:38',
    '0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-18 21:05:38', 2, 0
  ),
  (
    '0_0_e7b9049e8ad34a78af90286b63f4759c', '角色管理',
    '0_0_661824d0f33441aba8236d5be366434f', NULL, 2,
    '0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-18 21:04:57',
    '0_0_4c7b563b83fc410c957d08403b9e25ff', '2024-03-18 21:04:57', 3, 0
  ),
  (
    '0_0_f887ea1dc38341559285926c54123516', '添加',
    '0_0_99cad34fd9814ff4a8c88e72d60a552d', NULL, 3, '0_0_4c7b563b83fc410c957d08403b9e25ff',
    '2024-03-19 09:54:26', '0_0_4c7b563b83fc410c957d08403b9e25ff','2024-03-19 09:54:26', 1, 0
  ) ;

代码实现

Menu实体类,每个属性对应数据库的字段:


import java.sql.Timestamp;

public class Menu {
private String id;     // 主键
    private String name;   // 菜单名称
    private String parentId;      // 父级菜单id
    private String icon;          // 图标
    private Integer type;         // 类型 1=目录,2=菜单,3=按钮
    private String createId;      // 创建者ID
    private Timestamp createTime; // 创建时间
    private String updateId;      // 更新者ID
    private Timestamp updateTime; // 更新时间
    private Integer no;           // 顺序
    private Integer delFlag;      // 是否删除
    // getter/setters 忽略
}

Menu的DTO类,用来保存树形结构:

private String id;     // 主键
    private List<String> ids;
    private String name;   // 菜单名称
    private String parentId;      // 父级菜单id
    private List<String> parentIds;
    private String icon;          // 图标
    private Integer code;         // 菜单编码
    private Integer type;         // 类型 字典menu_type
    private String createId;      // 创建者ID
    private Timestamp createTime; // 创建时间
    private String updateId;      // 更新者ID
    private Timestamp updateTime; // 更新时间
    private Integer no;           // 顺序
    private Integer delFlag;      // 是否删除

    private List<MenuDto> children = new ArrayList<>();

    private String orderBy;
    private String asc;
// getter/setters 忽略

mybatis的MenuMapper接口:

package zhangchao.readdbtree;

import java.util.List;
import org.apache.ibatis.annotations.Param;

public interface MenuMapper {
    Menu selectById(@Param("id") String id);
    List<Menu> selectList(MenuDto menuDto);
}

MenuMapper.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="zhangchao.readdbtree.MenuMapper">
    <resultMap id="rm" type="zhangchao.readdbtree.Menu">
        <id property="id" column="c_id"/>
        <result property="name" column="c_name"/>
        <result property="parentId" column="c_parent_id"/>
        <result property="icon" column="c_icon"/>
        <result property="type" column="c_type"/>
        <result property="createId" column="c_create_id"/>
        <result property="createTime" column="c_create_time"/>
        <result property="updateId" column="c_update_id"/>
        <result property="updateTime" column="c_update_time"/>
        <result property="no" column="c_no"/>
        <result property="delFlag" column="c_del_flag"/>
    </resultMap>


    <select id="selectById" resultMap="rm">
        select * from t_menu where c_id=#{id}
    </select>


    <select id="selectList" resultMap="rm">
        select * from t_menu where 1=1
        <if test="name != null">
            and c_name like concat('%', #{name}, '%')
        </if>
        <if test="parentId != null">
            and c_parent_id = #{parentId}
        </if>
        <if test="parentIds != null and parentIds.size() > 0">
            and c_parent_id in
            <foreach collection="parentIds" open="(" close=")" separator="," item="item">
                #{item}
            </foreach>
        </if>
        <if test="type != null">
            and c_type = #{type}
        </if>
        <if test="delFlag != null">
            and c_del_flag = #{delFlag}
        </if>
        <if test="ids != null and ids.size() > 0">
            and c_id in
            <foreach collection="ids" open="(" close=")" separator="," item="item">
                #{item}
            </foreach>
        </if>

        <if test="orderBy != null and asc != null">
            order by ${orderBy} ${asc}
        </if>
    </select>
</mapper>

mybatis-config.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/test"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="mapper/CityMapper.xml"/>
        <mapper resource="mapper/MenuMapper.xml"/>
<!--        <mapper resource="mapper/LogMapper.xml"/>-->
    </mappers>
</configuration>

加载mybatis的类DBFactory

package zhangchao.common.db;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

public class DBFactory {
    private static SqlSessionFactory sqlSessionFactory = null;

    static {
        String resource = "mybatis-config.xml";
        InputStream inputStream = null;
        try {
            inputStream = Resources.getResourceAsStream(resource);
        } catch (IOException e) {
            e.printStackTrace();
        }
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }

    public static SqlSessionFactory getInstance(){
        return sqlSessionFactory;
    }

}

整个算法的核心类MenuService,该类包含了三个算法:

  1. 查找整棵树的树形结构
  2. 根据若干ID查找对应的树节点,并按照树形结构返回结果。
  3. 传入某个节点的ID,把以该节点为根的子树都查找出来

具体代码如下:

package zhangchao.readdbtree;

import org.apache.ibatis.session.SqlSession;
import zhangchao.common.db.DBFactory;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author zhangchao
 */
public class MenuService {

    private void menuToDto(Menu menu, MenuDto menuDto) {
        menuDto.setId(menu.getId());
        menuDto.setName(menu.getName());
        menuDto.setParentId(menu.getParentId());
        menuDto.setIcon(menu.getIcon());
        menuDto.setType(menu.getType());
        menuDto.setNo(menu.getNo());
    }

    /**
     * 查找整棵树的树形结构
     * @return 整棵树的树形结构
     */
    public List<MenuDto> allMenuTree() {
        List<MenuDto> result = new ArrayList<>();
        MenuDto sqlParam = new MenuDto();
        sqlParam.setParentId("-1");
        sqlParam.setDelFlag(0);
        sqlParam.setOrderBy("c_no");
        sqlParam.setAsc("asc");
        SqlSession sqlSession = DBFactory.getInstance().openSession(true);
        MenuMapper menuMapper = sqlSession.getMapper(MenuMapper.class);
        try {
            // 先把顶层加入result
            List<Menu> menuList_1 = menuMapper.selectList(sqlParam);
            for (Menu menu_1 : menuList_1) {
                MenuDto menuDto_1 = new MenuDto();
                this.menuToDto(menu_1, menuDto_1);
                result.add(menuDto_1);
            }

            List<MenuDto> currentLevel = result;
            while (currentLevel != null && !currentLevel.isEmpty()) {
                List<String> parentIds = new ArrayList<>();
                Map<String, MenuDto> map = new HashMap<>();
                for (MenuDto dto : currentLevel) {
                    String id = dto.getId();
                    parentIds.add(id);
                    map.put(id, dto);
                    if (dto.getChildren() == null) {
                        dto.setChildren(new ArrayList<>());
                    }
                }
                sqlParam.setParentId(null);
                sqlParam.setParentIds(parentIds);
                List<Menu> dbNextLevel = menuMapper.selectList(sqlParam);
                List<MenuDto> nextLevel = new ArrayList<>();
                if (dbNextLevel != null && !dbNextLevel.isEmpty()) {
                    for (Menu menu : dbNextLevel) {
                        MenuDto menuDto = new MenuDto();
                        this.menuToDto(menu, menuDto);
                        map.get(menu.getParentId()).getChildren().add(menuDto);
                        nextLevel.add(menuDto);
                    }
                }
                currentLevel = nextLevel;
            }

        } finally {
            sqlSession.close();
        }
        return result;
    }

    /**
     * 根据若干ID查找对应的树节点,并按照树形结构返回结果。
     * @param ids 树节点ID列表
     * @return 树形结构
     */
    public List<MenuDto> selectMenuTreeByIds(List<String> ids) {
        List<MenuDto> result = new ArrayList<>();
        MenuDto sqlParam = new MenuDto();
        sqlParam.setIds(ids);
        sqlParam.setParentId("-1");
        sqlParam.setDelFlag(0);
        sqlParam.setOrderBy("c_no");
        sqlParam.setAsc("asc");
        SqlSession sqlSession = DBFactory.getInstance().openSession(true);
        MenuMapper menuMapper = sqlSession.getMapper(MenuMapper.class);
        try {
            // 先把顶层加入result
            List<Menu> menuList_1 = menuMapper.selectList(sqlParam);
            for (Menu menu_1 : menuList_1) {
                MenuDto menuDto_1 = new MenuDto();
                this.menuToDto(menu_1, menuDto_1);
                result.add(menuDto_1);
            }

            List<MenuDto> curentLevel = result;
            while (curentLevel != null && !curentLevel.isEmpty()) {
                List<String> parentIds = new ArrayList<>();
                Map<String, MenuDto> map = new HashMap<>();
                // 这个for循环是为了给 parentIds 和 map 添加元素。
                for (MenuDto dto : curentLevel) {
                    String id = dto.getId();
                    parentIds.add(id);
                    map.put(id, dto);
                    if (dto.getChildren() == null) {
                        dto.setChildren(new ArrayList<>());
                    }
                }
                // 设置查询下一级节点的参数。
                sqlParam.setParentId(null);
                sqlParam.setParentIds(parentIds);
                // 从数据库中查询下一级节点。
                List<Menu> dbNextLevel = menuMapper.selectList(sqlParam);
                // 下一级节点的dto列表。
                List<MenuDto> nextLevel = new ArrayList<>();
                if (dbNextLevel != null && !dbNextLevel.isEmpty()) {
                    for (Menu menu : dbNextLevel) {
                        MenuDto menuDto = new MenuDto();
                        this.menuToDto(menu, menuDto);
                        map.get(menu.getParentId()).getChildren().add(menuDto);
                        nextLevel.add(menuDto);
                    }
                }
                curentLevel = nextLevel;
            }
        } finally {
            sqlSession.close();
        }
        return result;
    }

    /**
     * 传入某个节点的ID,把以该节点为根的子树都查找出来
     * @param subRootId 节点ID
     * @return 以传入节点为根的子树
     */
    public List<MenuDto> subTree(String subRootId) {
        List<MenuDto> result = new ArrayList<>();
        SqlSession sqlSession = DBFactory.getInstance().openSession(true);
        MenuMapper menuMapper = sqlSession.getMapper(MenuMapper.class);
        try {
            Menu root = menuMapper.selectById(subRootId);
            // 先把顶层加入result
            List<Menu> menuList_1 = new ArrayList<>();
            if (root != null && root.getDelFlag() == 0) {
                menuList_1.add(root);
            }
            for (Menu menu_1 : menuList_1) {
                MenuDto menuDto_1 = new MenuDto();
                this.menuToDto(menu_1, menuDto_1);
                result.add(menuDto_1);
            }

            MenuDto sqlParam = new MenuDto();
            sqlParam.setDelFlag(0);
            sqlParam.setOrderBy("c_no");
            sqlParam.setAsc("asc");

            List<MenuDto> curentLevel = result;
            while (curentLevel != null && !curentLevel.isEmpty()) {
                List<String> parentIds = new ArrayList<>();
                Map<String, MenuDto> map = new HashMap<>();
                // 这个for循环是为了给 parentIds 和 map 添加元素。
                for (MenuDto dto : curentLevel) {
                    String id = dto.getId();
                    parentIds.add(id);
                    map.put(id, dto);
                    if (dto.getChildren() == null) {
                        dto.setChildren(new ArrayList<>());
                    }
                }
                // 设置查询下一级节点的参数。
                sqlParam.setParentId(null);
                sqlParam.setParentIds(parentIds);
                // 从数据库中查询下一级节点。
                List<Menu> dbNextLevel = menuMapper.selectList(sqlParam);
                // 下一级节点的dto列表。
                List<MenuDto> nextLevel = new ArrayList<>();
                if (dbNextLevel != null && !dbNextLevel.isEmpty()) {
                    for (Menu menu : dbNextLevel) {
                        MenuDto menuDto = new MenuDto();
                        this.menuToDto(menu, menuDto);
                        map.get(menu.getParentId()).getChildren().add(menuDto);
                        nextLevel.add(menuDto);
                    }
                }
                curentLevel = nextLevel;
            }
        } finally {
            sqlSession.close();
        }
        return result;
    }
}

调用类TestReadDbTree:

package zhangchao.readdbtree;

import com.google.gson.Gson;

import java.util.ArrayList;
import java.util.List;

public class TestReadDbTree {

    public static void main(String[] args) {
        MenuService menuService = new MenuService();
        List<MenuDto> allTree = menuService.allMenuTree();
        Gson gson = new Gson();
        // 整棵树
        System.out.println(gson.toJson(allTree));

        // 选中的部分树节点
        List<String> ids = new ArrayList<>();
        ids.add("0_0_661824d0f33441aba8236d5be366434f");
        ids.add("0_0_99cad34fd9814ff4a8c88e72d60a552d");
        ids.add("0_0_61379d8d12b3456797188a9044d14f3c");
        ids.add("0_0_01ec9a90f6b34439bb979e4fad37852b");
        ids.add("0_0_acf36bbee31541ad874af0b78de92ff5");
        List<MenuDto> selectedTree = menuService.selectMenuTreeByIds(ids);
        System.out.println(gson.toJson(selectedTree));

        // 传入某个节点的ID,把以该节点为根的子树都查找出来
        List<MenuDto> subTree = menuService.subTree("0_0_99cad34fd9814ff4a8c88e72d60a552d");
        System.out.println(gson.toJson(subTree));
    }
}

输出结果

整棵树形结构:

[
    {
        "id": "0_0_661824d0f33441aba8236d5be366434f",
        "name": "系统管理",
        "parentId": "-1",
        "type": 1,
        "no": 1,
        "children": [
            {
                "id": "0_0_99cad34fd9814ff4a8c88e72d60a552d",
                "name": "用户管理",
                "parentId": "0_0_661824d0f33441aba8236d5be366434f",
                "type": 2,
                "no": 1,
                "children": [
                    {
                        "id": "0_0_f887ea1dc38341559285926c54123516",
                        "name": "添加",
                        "parentId": "0_0_99cad34fd9814ff4a8c88e72d60a552d",
                        "type": 3,
                        "no": 1,
                        "children": []
                    },
                    {
                        "id": "0_0_c8085841164547a5834d51eb7d3f566f",
                        "name": "修改",
                        "parentId": "0_0_99cad34fd9814ff4a8c88e72d60a552d",
                        "type": 3,
                        "no": 2,
                        "children": []
                    },
                    {
                        "id": "0_0_3de80520f6f74b2386b8381a564c4e09",
                        "name": "删除",
                        "parentId": "0_0_99cad34fd9814ff4a8c88e72d60a552d",
                        "type": 3,
                        "no": 3,
                        "children": []
                    },
                    {
                        "id": "0_0_a3486bd0026f47c298b5d2d55db6f733",
                        "name": "重置密码",
                        "parentId": "0_0_99cad34fd9814ff4a8c88e72d60a552d",
                        "type": 3,
                        "no": 4,
                        "children": []
                    },
                    {
                        "id": "0_0_a88b254640f94f3c9afab62ef10dbedb",
                        "name": "分配角色",
                        "parentId": "0_0_99cad34fd9814ff4a8c88e72d60a552d",
                        "type": 3,
                        "no": 5,
                        "children": []
                    }
                ]
            },
            {
                "id": "0_0_da9e85f955f44e16bfa8a20659de30d7",
                "name": "菜单管理",
                "parentId": "0_0_661824d0f33441aba8236d5be366434f",
                "type": 2,
                "no": 2,
                "children": [
                    {
                        "id": "0_0_843138ca616b466b8904c53c31b1bd2e",
                        "name": "添加",
                        "parentId": "0_0_da9e85f955f44e16bfa8a20659de30d7",
                        "type": 3,
                        "no": 1,
                        "children": []
                    },
                    {
                        "id": "0_0_d00f45f79a1941ad9adc0567352e6670",
                        "name": "修改",
                        "parentId": "0_0_da9e85f955f44e16bfa8a20659de30d7",
                        "type": 3,
                        "no": 2,
                        "children": []
                    },
                    {
                        "id": "0_0_545fb128881f462f8bc828b54e19e034",
                        "name": "删除",
                        "parentId": "0_0_da9e85f955f44e16bfa8a20659de30d7",
                        "type": 3,
                        "no": 3,
                        "children": []
                    }
                ]
            },
            {
                "id": "0_0_e7b9049e8ad34a78af90286b63f4759c",
                "name": "角色管理",
                "parentId": "0_0_661824d0f33441aba8236d5be366434f",
                "type": 2,
                "no": 3,
                "children": [
                    {
                        "id": "0_0_729b70ba39144dbb930547d39e4700b0",
                        "name": "添加",
                        "parentId": "0_0_e7b9049e8ad34a78af90286b63f4759c",
                        "type": 3,
                        "no": 1,
                        "children": []
                    },
                    {
                        "id": "0_0_6a71439c4de84eb19f99648df760c9c0",
                        "name": "修改",
                        "parentId": "0_0_e7b9049e8ad34a78af90286b63f4759c",
                        "type": 3,
                        "no": 2,
                        "children": []
                    },
                    {
                        "id": "0_0_a695d1d7a5c243379ceae6560855496e",
                        "name": "删除",
                        "parentId": "0_0_e7b9049e8ad34a78af90286b63f4759c",
                        "type": 3,
                        "no": 3,
                        "children": []
                    },
                    {
                        "id": "0_0_0ab19e321a5f490e9015f6e4cd496d27",
                        "name": "分配菜单",
                        "parentId": "0_0_e7b9049e8ad34a78af90286b63f4759c",
                        "type": 3,
                        "no": 4,
                        "children": []
                    }
                ]
            },
            {
                "id": "0_0_c982f477026541848405484f08ff1dfa",
                "name": "接口权限",
                "parentId": "0_0_661824d0f33441aba8236d5be366434f",
                "type": 2,
                "no": 4,
                "children": [
                    {
                        "id": "0_0_634317d8797e4aacb467e348a1ac8924",
                        "name": "添加",
                        "parentId": "0_0_c982f477026541848405484f08ff1dfa",
                        "type": 2,
                        "no": 1,
                        "children": []
                    },
                    {
                        "id": "0_0_bf244c78e686400db9808cd5fb0c3c91",
                        "name": "修改",
                        "parentId": "0_0_c982f477026541848405484f08ff1dfa",
                        "type": 2,
                        "no": 2,
                        "children": []
                    },
                    {
                        "id": "0_0_090d3da1301841f6b43e3a3ff2b44f68",
                        "name": "删除",
                        "parentId": "0_0_c982f477026541848405484f08ff1dfa",
                        "type": 2,
                        "no": 3,
                        "children": []
                    }
                ]
            }
        ]
    },
    {
        "id": "0_0_61379d8d12b3456797188a9044d14f3c",
        "name": "智慧农业",
        "parentId": "-1",
        "type": 1,
        "no": 2,
        "children": [
            {
                "id": "0_0_01ec9a90f6b34439bb979e4fad37852b",
                "name": "百叶箱数据",
                "parentId": "0_0_61379d8d12b3456797188a9044d14f3c",
                "type": 2,
                "no": 1,
                "children": [
                    {
                        "id": "0_0_acf36bbee31541ad874af0b78de92ff5",
                        "name": "删除",
                        "parentId": "0_0_01ec9a90f6b34439bb979e4fad37852b",
                        "type": 3,
                        "no": 1,
                        "children": []
                    }
                ]
            }
        ]
    }
]

选中的节点

[
    {
        "id": "0_0_661824d0f33441aba8236d5be366434f",
        "name": "系统管理",
        "parentId": "-1",
        "type": 1,
        "no": 1,
        "children": [
            {
                "id": "0_0_99cad34fd9814ff4a8c88e72d60a552d",
                "name": "用户管理",
                "parentId": "0_0_661824d0f33441aba8236d5be366434f",
                "type": 2,
                "no": 1,
                "children": []
            }
        ]
    },
    {
        "id": "0_0_61379d8d12b3456797188a9044d14f3c",
        "name": "智慧农业",
        "parentId": "-1",
        "type": 1,
        "no": 2,
        "children": [
            {
                "id": "0_0_01ec9a90f6b34439bb979e4fad37852b",
                "name": "百叶箱数据",
                "parentId": "0_0_61379d8d12b3456797188a9044d14f3c",
                "type": 2,
                "no": 1,
                "children": [
                    {
                        "id": "0_0_acf36bbee31541ad874af0b78de92ff5",
                        "name": "删除",
                        "parentId": "0_0_01ec9a90f6b34439bb979e4fad37852b",
                        "type": 3,
                        "no": 1,
                        "children": []
                    }
                ]
            }
        ]
    }
]

某棵子树

[
    {
        "id": "0_0_99cad34fd9814ff4a8c88e72d60a552d",
        "name": "用户管理",
        "parentId": "0_0_661824d0f33441aba8236d5be366434f",
        "type": 2,
        "no": 1,
        "children": [
            {
                "id": "0_0_f887ea1dc38341559285926c54123516",
                "name": "添加",
                "parentId": "0_0_99cad34fd9814ff4a8c88e72d60a552d",
                "type": 3,
                "no": 1,
                "children": [
                    {
                        "id": "0_0_3983284d54104f359b8406a50fa45632",
                        "name": "4444",
                        "parentId": "0_0_f887ea1dc38341559285926c54123516",
                        "type": 3,
                        "no": 1,
                        "children": []
                    }
                ]
            },
            {
                "id": "0_0_c8085841164547a5834d51eb7d3f566f",
                "name": "修改",
                "parentId": "0_0_99cad34fd9814ff4a8c88e72d60a552d",
                "type": 3,
                "no": 2,
                "children": []
            },
            {
                "id": "0_0_3de80520f6f74b2386b8381a564c4e09",
                "name": "删除",
                "parentId": "0_0_99cad34fd9814ff4a8c88e72d60a552d",
                "type": 3,
                "no": 3,
                "children": []
            },
            {
                "id": "0_0_a3486bd0026f47c298b5d2d55db6f733",
                "name": "重置密码",
                "parentId": "0_0_99cad34fd9814ff4a8c88e72d60a552d",
                "type": 3,
                "no": 4,
                "children": []
            },
            {
                "id": "0_0_a88b254640f94f3c9afab62ef10dbedb",
                "name": "分配角色",
                "parentId": "0_0_99cad34fd9814ff4a8c88e72d60a552d",
                "type": 3,
                "no": 5,
                "children": []
            }
        ]
    }
]
  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的Java代码示例,使用MySQL数据库来实现树形结构图。 1. 创建MySQL数据库表 在MySQL数据库创建一个名为“tree”的表,包含以下字段: - id:节点的唯一标识符,类型为INT - name:节点的名称,类型为VARCHAR - parent_id:父节点的ID,类型为INT CREATE TABLE tree ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50), parent_id INT ); 2. 创建Java类 创建一个名为“TreeNode”的Java类,用于表示树节点。该类包含以下属性: - id:节点的唯一标识符,类型为int - name:节点的名称,类型为String - children:子节点列表,类型为List<TreeNode> public class TreeNode { private int id; private String name; private List<TreeNode> children; public TreeNode(int id, String name) { this.id = id; this.name = name; this.children = new ArrayList<>(); } // getter and setter methods omitted for brevity } 3. 实现树的构建方法 创建一个名为“buildTree”的静态方法,用于从MySQL数据库读取数据并构建树结构。该方法使用递归算法实现。 public static TreeNode buildTree(Connection conn, int parentId) throws SQLException { String sql = "SELECT * FROM tree WHERE parent_id = ?"; PreparedStatement stmt = conn.prepareStatement(sql); stmt.setInt(1, parentId); ResultSet rs = stmt.executeQuery(); TreeNode parent = null; while (rs.next()) { int id = rs.getInt("id"); String name = rs.getString("name"); TreeNode node = new TreeNode(id, name); if (parent == null) { parent = node; } else { parent.getChildren().add(node); } buildTree(conn, id); } return parent; } 4. 测试代码 在main方法创建一个MySQL数据库连接,并调用buildTree方法构建树结构。 public static void main(String[] args) { String url = "jdbc:mysql://localhost:3306/test"; String user = "root"; String password = "password"; try (Connection conn = DriverManager.getConnection(url, user, password)) { TreeNode root = buildTree(conn, 0); // TODO: traverse the tree and display it } catch (SQLException e) { e.printStackTrace(); } } 上述代码的TODO部分应该是遍历树并在控制台上显示它的代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值