java-树状结构展示-递归查询

该博客介绍了如何使用Java后端结合MyBatis-Plus进行一次性数据库查询,并通过递归方式构造树状结构数据,以高效地提供前端展示。示例代码包括了Controller、Service、Mapper及实体类的实现,展示了如何处理层级关系并避免多次数据库查询。同时,提供了SQL语句和配置文件,展示了数据存储结构和应用设置。
摘要由CSDN通过智能技术生成

提供前端树形结构展示返回值

递归查询的时候千万不要多次查库,这样如果数据量大的时候特别影响性能,一定改成只查询一次库把数据放到缓存中继续递归操作。

查询结果

[{
		"name": "节点1",
		"id": 1,
		"parentId": -1,
		"children": [{
				"name": "节点1-1",
				"id": 4,
				"parentId": 1,
				"children": [{
						"children": [],
						"name": "节点1-1-1",
						"id": 13,
						"parentId": 4
					},
					{
						"children": [],
						"name": "节点1-1-2",
						"id": 14,
						"parentId": 4
					},
					{
						"children": [],
						"name": "节点1-1-3",
						"id": 15,
						"parentId": 4
					}
				]
			},
			{
				"name": "节点1-2",
				"id": 5,
				"parentId": 1,
				"children": [{
						"children": [],
						"name": "节点1-2-1",
						"id": 16,
						"parentId": 5
					},
					{
						"children": [],
						"name": "节点1-2-2",
						"id": 17,
						"parentId": 5
					},
					{
						"children": [],
						"name": "节点1-2-3",
						"id": 18,
						"parentId": 5
					}
				]
			},
			{
				"name": "节点1-3",
				"id": 6,
				"parentId": 1,
				"children": [{
						"children": [],
						"name": "节点1-3-1",
						"id": 19,
						"parentId": 6
					},
					{
						"children": [],
						"name": "节点1-3-2",
						"id": 20,
						"parentId": 6
					},
					{
						"children": [],
						"name": "节点1-3-3",
						"id": 21,
						"parentId": 6
					}
				]
			}
		]
	},
	{
		"name": "节点2",
		"id": 2,
		"parentId": -1,
		"children": [{
				"children": [],
				"name": "节点2-1",
				"id": 7,
				"parentId": 2
			},
			{
				"children": [],
				"name": "节点2-2",
				"id": 8,
				"parentId": 2
			},
			{
				"children": [],
				"name": "节点2-3",
				"id": 9,
				"parentId": 2
			}
		]
	},
	{
		"name": "节点3",
		"id": 3,
		"parentId": -1,
		"children": [{
				"children": [],
				"name": "节点3-1",
				"id": 10,
				"parentId": 3
			},
			{
				"children": [],
				"name": "节点3-2",
				"id": 11,
				"parentId": 3
			},
			{
				"children": [],
				"name": "节点3-3",
				"id": 12,
				"parentId": 3
			}
		]
	}
]

pom.xml

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.29</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.1</version>
        </dependency>

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-core</artifactId>
            <version>3.5.1</version>
        </dependency>

控制层代码 Controller

import com.tree.entity.TreeVO;
import com.tree.service.TreeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
public class TreeController {
    @Autowired
    private TreeService treeService;

    @GetMapping("/tree")
    public List<TreeVO> selectList(@RequestParam(value = "parentId", required = false) Integer parentId) {
        List<TreeVO> tagManageDTOList = treeService.selectTree(parentId);
        return tagManageDTOList;
    }
}

业务实现层代码 Service


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.tree.entity.Tree;
import com.tree.entity.TreeVO;
import com.tree.mapper.TreeMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

@Service
public class TreeService {

    @Autowired
    private TreeMapper treeMapper;

    /**
     * 将数据库查出来的所有数据保存到缓存种,避免多次调用数据库
     */
    private List<Tree> trees;

    /**
     * 查询树状结构
     *
     * @param parentId 根节点获取树分支,如果是0 获取所有根节点分支
     * @return
     */
    public List<TreeVO> selectTree(Integer parentId) {
        //初始化数据
        this.trees = treeMapper.selectList(new QueryWrapper<Tree>());
        return getTree(parentId != null ? parentId : -1);
    }

    /**
     * 获取树结构
     *
     * @param parentId
     * @return
     */
    private List<TreeVO> getTree(Integer parentId) {
        List<TreeVO> selectListByParentIdList = selectListByParentId(parentId);
        if (selectListByParentIdList.size() > 0) {
            for (Integer i = 0; i < selectListByParentIdList.size(); i++) {
                List<TreeVO> treeVOList = getTree(selectListByParentIdList.get(i).getId());
                selectListByParentIdList.get(i).setChildren(treeVOList);
            }
        }
        return selectListByParentIdList;
    }

    /**
     * 根据parentId获取分支数量
     *
     * @param parentId
     * @return
     */
    private List<TreeVO> selectListByParentId(Integer parentId) {
        List<TreeVO> treeVOList = new ArrayList<>();
        this.trees.forEach(tree -> {
            if (parentId == tree.getParentId()) {
                TreeVO treeVO = new TreeVO();
                BeanUtils.copyProperties(tree, treeVO);
                treeVOList.add(treeVO);
            }
        });
        return treeVOList;
    }

}

数据存储对象 Mapper / DAO

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.tree.entity.Tree;
import org.springframework.stereotype.Repository;

@Repository
public interface TreeMapper extends BaseMapper<Tree> {

}

实体类

Tree
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

/**
 * 数据库实体类
 */
@Data
@TableName("tree_table")
public class Tree {

    private Integer id;

    private String name;

    /**
     * 父id
     */
    private Integer parentId;
}

TreeVO
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;

import java.util.List;

/**
 *  返回结果实体类
 */
@Data
public class TreeVO {

    private Integer id;

    private String name;

    /**
     * 父id
     */
    private Integer parentId;

    /**
     * 子属性
     */
    private List<TreeVO> children;
}

sql语句

/*
Navicat MySQL Data Transfer

Source Server         : 127.0.0.1
Source Server Version : 50717
Source Host           : 127.0.0.1:3306
Source Database       : demo

Target Server Type    : MYSQL
Target Server Version : 50717
File Encoding         : 65001

Date: 2022-11-09 10:15:11
*/

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for `tree_table`
-- ----------------------------
DROP TABLE IF EXISTS `tree_table`;
CREATE TABLE `tree_table` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(32) NOT NULL,
  `parent_id` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of tree_table
-- ----------------------------
INSERT INTO `tree_table` VALUES ('1', '节点1', '-1');
INSERT INTO `tree_table` VALUES ('2', '节点2', '-1');
INSERT INTO `tree_table` VALUES ('3', '节点3', '-1');
INSERT INTO `tree_table` VALUES ('4', '节点1-1', '1');
INSERT INTO `tree_table` VALUES ('5', '节点1-2', '1');
INSERT INTO `tree_table` VALUES ('6', '节点1-3', '1');
INSERT INTO `tree_table` VALUES ('7', '节点2-1', '2');
INSERT INTO `tree_table` VALUES ('8', '节点2-2', '2');
INSERT INTO `tree_table` VALUES ('9', '节点2-3', '2');
INSERT INTO `tree_table` VALUES ('10', '节点3-1', '3');
INSERT INTO `tree_table` VALUES ('11', '节点3-2', '3');
INSERT INTO `tree_table` VALUES ('12', '节点3-3', '3');
INSERT INTO `tree_table` VALUES ('13', '节点1-1-1', '4');
INSERT INTO `tree_table` VALUES ('14', '节点1-1-2', '4');
INSERT INTO `tree_table` VALUES ('15', '节点1-1-3', '4');
INSERT INTO `tree_table` VALUES ('16', '节点1-2-1', '5');
INSERT INTO `tree_table` VALUES ('17', '节点1-2-2', '5');
INSERT INTO `tree_table` VALUES ('18', '节点1-2-3', '5');
INSERT INTO `tree_table` VALUES ('19', '节点1-3-1', '6');
INSERT INTO `tree_table` VALUES ('20', '节点1-3-2', '6');
INSERT INTO `tree_table` VALUES ('21', '节点1-3-3', '6');

application.yml

server:
  port: 8888

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf-8&useSSL=true
    username: root
    password: root

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #开启sql日志

个人喜欢把实体类区分化,如果不喜欢区分,需要在 children 属性中添加 @TableField(exist = false) ,以免利用苞米豆查询报错

@TableField(exist = false)
private List<TreeVO> children;
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值