前言
日常开发中可能会遇到一些需求,比如构建菜单,构建树形结构,数据库一般就使用父id来表示,为了降低数据库的查询压力,我们可以使用Java8中的Stream流一次性把数据查出来,然后通过流式处理,转为树形结构。下面我们一起来看看怎么做。
1. 首先数据库菜单资源表数据如下:
2. SysMenuMapper.xml中SQL如下:
<?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="com.pfms.master.mapper.SysMenuMapper">
<resultMap id="BaseResultMap" type="com.pfms.master.entity.SysMenu">
<id column="ID" property="id" />
<result column="URL" property="url" />
<result column="PATH" property="path" />
<result column="COMPONENT" property="component" />
<result column="NAME" property="name" />
<result column="ICON" property="icon" />
<result column="PARENT_ID" property="parentId" />
<result column="KEEP_ALIVE" property="keepAlive" />
<result column="REQUIRE_AUTH" property="requireAuth" />
<result column="ENABLED" property="enabled" />
<result column="REMARK" property="remark" />
<result column="CREATE_BY" property="createBy" />
<result column="CREATE_DATE" property="createDate" />
<result column="UPDATE_BY" property="updateBy" />
<result column="UPDATE_DATE" property="updateDate" />
<association property="meta" javaType="com.pfms.master.entity.domain.Meta">
<result column="keepAlive" property="keepAlive"/>
<result column="requireAuth" property="requireAuth"/>
</association>
</resultMap>
<select id="getMenusByUserId_" resultMap="BaseResultMap">
SELECT
*
FROM
`sys_menu`
WHERE
ID IN ( SELECT MENU_ID FROM sys_menu_role WHERE ROLE_ID IN ( SELECT ROLE_ID FROM sys_user_role WHERE USER_ID = #{userId} ) )
AND PATH IS NOT NULL
AND PATH != ''
ORDER BY
ID
</select>
</mapper>
3. 主要代码
List
<SysMenu> menus
= baseMapper
.getMenusByUserId_(userId
);
if (isNotEmpty(menus
)) {
resultMenus
= menus
.stream().filter(m
-> m
.getParentId() == 1).peek(
(m
) -> m
.setChildren(getChildren(m
, menus
))
).collect(Collectors
.toList());
}
4. 递归获取子节点的方法
private List
<SysMenu> getChildren(SysMenu m
, List
<SysMenu> menus
) {
return menus
.stream().filter(m1
-> m
.getId().equals(m1
.getParentId()))
.peek(m1
-> m1
.setChildren(getChildren(m1
, menus
))).collect(Collectors
.toList());
}