# 多级菜单数据结构 - 非递归
创建数据库表:
/* | |
Navicat Premium Data Transfer | |
Source Server : windows | |
Source Server Type : MySQL | |
Source Server Version : 80028 | |
Source Host : localhost:3306 | |
Source Schema : tree_data | |
Target Server Type : MySQL | |
Target Server Version : 80028 | |
File Encoding : 65001 | |
Date: 29/02/2024 11:26:32 | |
*/ | |
SET NAMES utf8mb4; | |
SET FOREIGN_KEY_CHECKS = 0; | |
-- ---------------------------- | |
-- Table structure for data_one | |
-- ---------------------------- | |
DROP TABLE IF EXISTS `data_one`; | |
CREATE TABLE `data_one` ( | |
`id` int NOT NULL AUTO_INCREMENT, | |
`name` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '', | |
`p_id` int NULL DEFAULT NULL, | |
`order_num` int NULL DEFAULT NULL, | |
PRIMARY KEY (`id`) USING BTREE | |
) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; | |
-- ---------------------------- | |
-- Records of data_one | |
-- ---------------------------- | |
INSERT INTO `data_one` VALUES (1, '邢台', 0, 1); | |
INSERT INTO `data_one` VALUES (2, '沙河市', 1, 2); | |
INSERT INTO `data_one` VALUES (3, '河北省', 1, 3); | |
INSERT INTO `data_one` VALUES (4, '北京 ', 0, 1); | |
INSERT INTO `data_one` VALUES (5, '朝阳', 4, 2); | |
INSERT INTO `data_one` VALUES (6, '赞善乡', 2, 1); | |
SET FOREIGN_KEY_CHECKS = 1; |
创建好表如下:
编写 java 代码:
实体类:
public class DataOne { | |
private Integer id; | |
private String name; | |
private Integer pId; | |
private Integer orderNum; // 排序字段 | |
private List<DataOne> data1s; // 子级菜单集合 | |
public List<DataOne> getData1s() { | |
return data1s; | |
} | |
public void setData1s(List<DataOne> data1s) { | |
this.data1s = data1s; | |
} | |
public Integer getId() { | |
return id; | |
} | |
public void setId(Integer id) { | |
this.id = id; | |
} | |
public String getName() { | |
return name; | |
} | |
public void setName(String name) { | |
this.name = name; | |
} | |
public Integer getpId() { | |
return pId; | |
} | |
public void setpId(Integer pId) { | |
this.pId = pId; | |
} | |
public Integer getOrderNum() { | |
return orderNum; | |
} | |
public void setOrderNum(Integer orderNum) { | |
this.orderNum = orderNum; | |
} | |
@Override | |
public String toString() { | |
return "Data1{" + | |
"id=" + id + | |
", name='" + name + '\'' + | |
", pId=" + pId + | |
", orderNum=" + orderNum + | |
", data1s=" + data1s + | |
'}'; | |
} | |
} |
创建 JdbcUtils 工具类:
public class JUtils { | |
private static DataSource source; | |
static{ | |
Properties pro = null; | |
try{ | |
pro = new Properties(); | |
InputStream in = JUtils.class.getClassLoader().getResourceAsStream("druid.properties"); | |
pro.load(in); | |
source = DruidDataSourceFactory.createDataSource(pro); | |
}catch(IOException e){ | |
throw new RuntimeException(e); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
} | |
public static Connection getConnection() throws SQLException { | |
return source.getConnection(); | |
} | |
public static DataSource getSource() { | |
return source; | |
} | |
} |
创建查询数据库并返回多级菜单数据结构的类:
public class TreeDataOne { | |
// 创建 JdbcTemplate 对象查询数据库 | |
private JdbcTemplate jdbcTemplate = new JdbcTemplate(JUtils.getSource()); | |
public List<DataOne> getTreeChildren() { | |
// 查询 data_one 表的所有数据 | |
String sql = "select * from data_one"; | |
List<DataOne> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<DataOne>(DataOne.class)); | |
// 调用函数将所有数据根据某字段来构建成树形结构并返回 | |
return buildTree(query); | |
} | |
public List<DataOne> buildTree(List<DataOne> listTree) { | |
// 创建 map 集合 | |
Map<Integer, DataOne> map = new HashMap<>(); | |
for (DataOne datas : listTree) { | |
// 存储 每条数据的 id 与它的数据 | |
map.put(datas.getId(), datas); | |
} | |
// 创建 List 集合 | |
List<DataOne> datalists = new ArrayList<>(); | |
for (DataOne data1 : listTree) { | |
// 获取遍历的每条数据的 pId | |
Integer parentId = data1.getpId(); | |
if (parentId == null || parentId == 0) { | |
datalists.add(data1); | |
}else { | |
DataOne dataOne = map.get(parentId); | |
if (dataOne != null) { | |
if (dataOne.getData1s() == null) { | |
dataOne.setData1s(new ArrayList<>()); | |
} | |
dataOne.getData1s().add(data1); | |
} | |
} | |
} | |
sortTree(datalists); | |
return datalists; | |
} | |
public void sortTree(List<DataOne> listTree) { | |
for (DataOne datas : listTree) { | |
if (datas.getData1s() != null && ! datas.getData1s().isEmpty()) { | |
sortTree(datas.getData1s()); | |
} | |
} | |
Collections.sort(listTree, Comparator.comparingInt(DataOne::getOrderNum)); | |
} | |
} |
测试代码:
// 多级菜单数据测试 | |
@Test | |
public void testTwo() { | |
TreeDataOne data1Service = new TreeDataOne(); | |
List<DataOne> treeChildren = data1Service.getTreeChildren(); | |
for (DataOne treeChild : treeChildren) { | |
System.out.println(treeChild); | |
} | |
} |
打印结果:
信息: {dataSource-1} inited
Data1{id=1, name='邢台', pId=0, orderNum=1, data1s=[Data1{id=2, name='沙河市', pId=1, orderNum=2, data1s=[Data1{id=6, name='赞善乡', pId=2, orderNum=1, data1s=null}]}, Data1{id=3, name='河北省', pId=1, orderNum=3, data1s=null}]}
Data1{id=4, name='北京 ', pId=0, orderNum=1, data1s=[Data1{id=5, name='朝阳', pId=4, orderNum=2, data1s=null}]}
格式化后的数据:
Data1 { | |
id = 1, name = '邢台', pId = 0, orderNum = 1, data1s = [Data1 { | |
id = 2, name = '沙河市', pId = 1, orderNum = 2, data1s = [Data1 { | |
id = 6, name = '赞善乡', pId = 2, orderNum = 1, data1s = null | |
}] | |
}, Data1 { | |
id = 3, name = '河北省', pId = 1, orderNum = 3, data1s = null | |
}] | |
} | |
Data1 { | |
id = 4, name = '北京 ', pId = 0, orderNum = 1, data1s = [Data1 { | |
id = 5, name = '朝阳', pId = 4, orderNum = 2, data1s = null | |
}] | |
} |