先查询第一层的数据,然后调用递归循环第一层的数据,查询父Id等于第一层的Id,执行完成后第一层一下的所有数据就全部查询出来了。。。

场景描述 :每个应用(最顶层,树的根) 下面是多级菜单  每个菜单下是多个按钮(最下层,叶子结点)

关联关系 id和pid

根节点 pid为空,可根据type=APP查询出根节点

查询出所有根节点,然后递归查出子孙节点

Menu 的 List<Menu> list 是该节点的子节点

public  List<Menu> getTreeList(String topId) {EntityWrapper wrapper = new EntityWrapper<Menu>();wrapper.eq("menu_type","CORP");wrapper.eq("type","APP");if(StringUtils.isNotBlank(topId)){wrapper.eq("id",topId);}List<Menu> firstmenus = this.selectList(wrapper);List<Menu> trees = getSubList(firstmenus);return trees;}private   List<Menu> getSubList(List<Menu> entityList) {for (int i = 0; i < entityList.size(); i++) {List<Menu> firstmenus = this.selectList(new EntityWrapper<Menu>().eq("pid",entityList.get(i).getId()).eq("menu_type","CORP"));if(firstmenus != null && firstmenus.size()>0){List<Menu> list2= this.selectList(new EntityWrapper<Menu>().eq("pid",entityList.get(i).getId()).eq("menu_type","CORP"));entityList.get(i).setList(list2);getSubList(entityList.get(i).getList());}}return entityList;}

树节点TreeNode 类 以便ztree渲染

package com.ps.uzkefu.util;import java.util.Collections;
import java.util.Comparator;
import java.util.List;/*** 展示类别树用的树节点类* <p/>* WuZhiWei* 2014-5-19* 添加类说明以及属性注释*/
public class TreeNode {/*** 节点id*/private String id;/*** 父节点id*/private String pId;/*** 节点内容*/private String name;/*** 是否展开*/private String open="false";private boolean childOuter=false;private boolean dropRoot=false;
//    是否是父节点private boolean isParent=false;/*** 不可移动成为父节点*/private boolean isEnd = false ;/*** 不可移动成为根节点*/private boolean nocheck= false ;private int level=0;
//   是否被选中private boolean checked=false;private boolean halfCheck=false;private boolean chkDisabled=false;private int other=0;private List<TreeNode> children;private Integer orderNum;//排序数字private Boolean leaf = true;//是否是最底层的叶子结点public TreeNode(String id, String pId, String name, String open, Integer orderNum) {this.id = id;this.pId = pId;this.name = name;this.open = open;this.orderNum = orderNum;}public TreeNode() {}public List<TreeNode> getChildren() {return children;}public void setChildren(List<TreeNode> children) {Collections.sort(children,new Comparator<TreeNode>() {@Overridepublic int compare(TreeNode o1, TreeNode o2) {// 返回值为int类型,大于0表示正序,小于0表示逆序return o1.getOrderNum()-o2.getOrderNum();}});this.children = children;}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getpId() {return pId;}public void setpId(String pId) {this.pId = pId;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getOpen() {return open;}public void setOpen(String open) {this.open = open;}public boolean isParent() {return isParent;}public void setParent(boolean isParent) {this.isParent = isParent;}public boolean isEnd() {return isEnd;}public void setEnd(boolean isEnd) {this.isEnd = isEnd;}public boolean isNocheck() {return nocheck;}public void setNocheck(boolean nocheck) {this.nocheck = nocheck;}public int getLevel() {return level;}public void setLevel(int level) {this.level = level;}public boolean isChecked() {return checked;}public void setChecked(boolean checked) {this.checked = checked;}public boolean isHalfCheck() {return halfCheck;}public void setHalfCheck(boolean halfCheck) {this.halfCheck = halfCheck;}public boolean isChkDisabled() {return chkDisabled;}public void setChkDisabled(boolean chkDisabled) {this.chkDisabled = chkDisabled;}public int getOther() {return other;}public void setOther(int other) {this.other = other;}public boolean isChildOuter() {return childOuter;}public void setChildOuter(boolean childOuter) {this.childOuter = childOuter;}public boolean isDropRoot() {return dropRoot;}public void setDropRoot(boolean dropRoot) {this.dropRoot = dropRoot;}public Integer getOrderNum() {return orderNum;}public void setOrderNum(Integer orderNum) {this.orderNum = orderNum;}public Boolean getLeaf() {return leaf;}public void setLeaf(Boolean leaf) {this.leaf = leaf;}
}

3、菜单类Menu

package com.ps.uzkefu.apps.oms.account.entity;import com.baomidou.mybatisplus.annotations.TableField;
import com.baomidou.mybatisplus.activerecord.Model;
import com.baomidou.mybatisplus.annotations.TableName;
import com.ps.uzkefu.base.BaseEntity;
import lombok.Getter;
import lombok.Setter;import java.math.BigDecimal;
import java.util.Date;
import java.util.List;/*** <p>* 菜单,权限配置说明:*   1.菜单分为两种类型,*   (1)页面跳转权限即 路由权限、如果是按钮需配置 module privilege,在页面按钮上添加class permission,添加属性:module-privilege="callcenter-playVoice"*   (2)api请求权限,需在对应controller方法添加     @Permission(module = "crm",privilege = "saveOrUpdate"),*        如果一个controller方法被多出应用,则module值需一致,且privilege值可用逗号分隔* </p>** @author WuZhiWei* @since 2018-06-22*/
@Setter
@Getter
@TableName("t_oms_menu")
public class Menu extends BaseEntity<Menu> {private static final long serialVersionUID = 1L;/*** 菜单类型 商家(CORP)、平台(PLATFORM) */@TableField("menu_type")private String menuType;/*** 菜单名称(与视图的文件夹名称和路由路径对应),如:system*/private String name;/*** 菜单标题 如:系统设置*/private String title;/*** 菜单图标样式 如:layui-icon-component*/private String icon;/*** 菜单路由地址,默认按照 name 解析。一旦设置,将优先按照 jump 设定的路由跳转*/private String jump;/*** 是否默认展子菜单,默认不展开 0不展开 1展开*/private Integer spread;/*** 顺序*/@TableField("show_order")private Integer showOrder;/*** 父级菜单id*/private String pid;private String module; //权限所属模块private String privilege; //权限/***  类型:(应用:APP、菜单:MENU、按钮:BUTTON)*/private String type;/***  应用描述*/private String description;/***  封面图*/@TableField("logo_url")private String logoUrl;/***  标签(热销:HOT、内测中:BETA)*/private String sign;/***  指导价*/@TableField("guide_price")private BigDecimal guidePrice;/***  售价*/private BigDecimal price;/***  详情内容*/private String detail;/***  是否默认开通(0 不开通 1开通)*/private Boolean open;/***  状态(上架:ONSALE、下架:OFFSALE)*/private String status;/***  浏览数*/@TableField("view_count")private Integer viewCount;/***  购买企业数*/@TableField("buy_count")private Integer buyCount;@TableField(exist = false)private List<Menu> list;@TableField(exist = false)private Boolean isExpire;@TableField(exist = false)private Boolean isBought;@TableField(exist = false)private String expireTimeText;public Menu() {}public Menu(String id, String corpCode, Integer isDel, String creater,Date createTime, Date lastModifyTime, String lastModify,String menuType, String name, String title, String icon,String jump, Integer spread, Integer showOrder, String pid,String module, String privilege) {this.id = id;this.corpCode = corpCode;this.isDel = isDel;this.creater = creater;this.createTime = createTime;this.lastModifyTime = lastModifyTime;this.lastModify = lastModify;this.menuType = menuType;this.name = name;this.title = title;this.icon = icon;this.jump = jump;this.spread = spread;this.showOrder = showOrder;this.pid = pid;this.module = module;this.privilege = privilege;}
}

菜单转为TreeNode

 /*** 获取根节点* @param appid 根节点id集合* @param checkedIds  选中节点的id集合* @return*/public  List<TreeNode> getTreeListAsTreeNode(List<String> appid,List<String> checkedIds) {EntityWrapper wrapper = new EntityWrapper<Menu>();wrapper.eq("menu_type","CORP");wrapper.eq("type","APP");if(appid !=null && appid.size()>0){wrapper.in("id",appid);}List<Menu> apps = this.selectList(wrapper);List<TreeNode> treeNodes =menuListToTreeNodeList(apps,checkedIds);List<TreeNode> trees = getSubListAsTreeNode(treeNodes,checkedIds);return trees;}/*** 递归渲染树* @param rootTreeNodes  树的根节点* @param checkedIds 选中节点的id集合* @return*/private   List<TreeNode> getSubListAsTreeNode(List<TreeNode> rootTreeNodes,List<String> checkedIds) {for (TreeNode rootTreeNode:rootTreeNodes) {List<Menu> firstMenus = this.selectList(new EntityWrapper<Menu>().eq("pid",rootTreeNode.getId()).eq("menu_type","CORP"));if(firstMenus != null && firstMenus.size()>0){List<Menu> secondMenus= this.selectList(new EntityWrapper<Menu>().eq("pid",rootTreeNode.getId()).eq("menu_type","CORP"));List<TreeNode> treeNodes = menuListToTreeNodeList(secondMenus,checkedIds);rootTreeNode.setChildren(treeNodes);getSubListAsTreeNode(rootTreeNode.getChildren(),checkedIds);}}return rootTreeNodes;}/*** 菜单集合转为树集合 以便 ztree渲染* @param menus* @param checkedIds 选中节点的id集合* @return*/private List<TreeNode> menuListToTreeNodeList(List<Menu> menus,List<String> checkedIds){List<TreeNode> treeNodes = new ArrayList<>();menus.forEach(menu -> {treeNodes.add(setCheckStatus(menuToTreeNode(menu),checkedIds));});return  treeNodes;}/*** 菜单 转为树节点 以便ztree渲染* @param menu* @return*/private TreeNode menuToTreeNode(Menu menu){TreeNode treeNode = new TreeNode();if (Objects.equals(menu.getType(),UkConstant.MENU_TYPE_BUTTON)){treeNode.setLeaf(true);treeNode.setParent(false);}else {treeNode.setParent(true);treeNode.setLeaf(false);}treeNode.setpId(menu.getPid());treeNode.setId(menu.getId());treeNode.setName(menu.getTitle());treeNode.setOpen("true");treeNode.setOrderNum(menu.getShowOrder());return treeNode;}/***   根据选中节点的集合设置树节点的选中状态* @param treeNode* @param checkedIds* @return*/private TreeNode setCheckStatus(TreeNode treeNode,List<String> checkedIds){if (checkedIds != null && checkedIds.size()>0){if (checkedIds.contains(treeNode.getId())){treeNode.setChecked(true);}}return  treeNode;}

经过一番思考 ,由于在递归中查询数据库,性能较差,改变思路

由于菜单表是树结构,表中有10个树的根节点,先查询出所有数据

封装成10棵树,然后再去掉不需要的树 代码如下

 @Overridepublic List<TreeNode> getMenuByCorpCodeAndRoleId(String corpCode, String roleId) {Assert.notNull(corpCode);Assert.notNull(roleId);//获取所有应用List<Menu> apps = this.selectList(new EntityWrapper<Menu>().eq("menu_type", UkConstant.CUSTOMER_TYPE_CORP).eq("type", UkConstant.MENU_TYPE_APP).orderBy("show_order"));//获取该公司购买的应用EntityWrapper<MenuCorp> wrapper = new EntityWrapper<MenuCorp>();wrapper.eq(ExecutionContext.CORP_CODE, corpCode).gt("expire_time", DateUtil.convert(new Date(), DateUtil.DATE_PATTERN_yyyy_MM_dd_HH_MM_ss));List<MenuCorp> corpApps = menuCorpService.selectList(wrapper);List<Menu> buyApps = new ArrayList<>();List<String> buyAppIds = new ArrayList<>(buyApps.size());for (MenuCorp corpApp : corpApps) {buyAppIds.add(corpApp.getMenuId());}for (Menu menu : apps) {if (buyAppIds.contains(menu.getId())) {buyApps.add(menu);}}List<RoleMenu> roleMenus = roleMenuService.selectList(new EntityWrapper<RoleMenu>().eq("role_id", roleId));List<String> checkIds = new ArrayList<>();for (RoleMenu rolemenu : roleMenus) {checkIds.add(rolemenu.getMenuId());}List<Menu> allMenus = this.selectList(new EntityWrapper<Menu>().orderBy("show_order"));List<TreeNode> treeNodes = menuToTreeNodes(allMenus,checkIds);List<TreeNode> tree = TreeUtils.formatTree(treeNodes,true,false);List<TreeNode> result = new ArrayList<>(buyAppIds.size());tree.forEach( treeNode -> {if (buyAppIds.contains(treeNode.getId())){result.add(treeNode);}});return result;}/*** 菜单集合转为树集合 以便 ztree渲染** @param menus* @param checkedIds 选中节点的id集合* @return*/private List<TreeNode> menuToTreeNodes(List<Menu> menus, List<String> checkedIds) {List<TreeNode> treeNodes = new ArrayList<>();menus.forEach(menu -> {treeNodes.add(menuToTreeNode(menu,checkedIds));});return treeNodes;}/*** 菜单 转为树节点 以便ztree渲染** @param menu* @return*/private TreeNode menuToTreeNode(Menu menu,List<String> checkedIds) {TreeNode treeNode = new TreeNode();if (Objects.equals(menu.getType(), UkConstant.MENU_TYPE_BUTTON)) {treeNode.setLeaf(true);treeNode.setParent(false);} else {treeNode.setParent(true);treeNode.setLeaf(false);}treeNode.setpId(menu.getPid());treeNode.setId(menu.getId());treeNode.setName(menu.getTitle());treeNode.setOpen("true");treeNode.setOrderNum(menu.getShowOrder());if (CollectionUtils.isNotEmpty(checkedIds) && checkedIds.contains(treeNode.getId())) {treeNode.setChecked(true);}return treeNode;}

java递归查询数据库树相关推荐

  1. java递归查询数据库数据

    先查询第一层的数据,然后调用递归循环第一层的数据,查询父Id等于第一层的Id,执行完成后第一层一下的所有数据就全部查询出来了... public List<Information> get ...

  2. Java让数据库执行一条sql_java数据库编程——执行SQL 语句

    [0]README [1]java数据库编程--执行SQL 语句相关 1)执行 SQL 命令前, 首先需要创建一个 Statement 对象: 要创建 statement 对象,不需要调用 Drive ...

  3. java递归查询分类及分类下所有子分类

    该案例是实际开发中运用,java递归查询分类及分类下所有子分类. 代码走起: 1.jsp页面布局样式这里不再介绍,js业务逻辑展示分类树形结构如下: /*** 商品分类操作*//*** 初始化*/ $ ...

  4. 旅游管理系统-JAVA【数据库设计、源码、开题报告】

    系统分析 本章将从整体上描述系统的需求,根据需求确定了系统的整体结构和数据库设计方案,对系统各部分的功能进行了划分并描述了系统架构的设计思路.本文将详细的分析系统的续期功能的设计及实现方法. 研究背景 ...

  5. 即将实习的应届毕业生 学习java SpringMVC 数据库 知识总结

    即将实习的应届毕业生 学习java SpringMVC 数据库 知识总结 1.Java语言的优点: 1)Java是纯面向对象语言 2)与平台无关性,一次编译到处运行 3)Java提供了狠多内置类库 4 ...

  6. JAVA MySQL数据库 笔记

    MySQL数据库 1. 初始MySQL 1.1 为什么学习数据库 岗位技能需求 现在的世界,得数据者得天下 网站中数据存储的地方 数据库是几乎软件体系中最核心的一个存在. 1.2 什么是数据库 数据库 ...

  7. Java开源数据库分类列表整理

    HSQLDB HSQLDB(Hypersonic SQL)是纯Java开发的关系型数据库,并提供JDBC驱动存取数据.支持ANSI-92 标准 SQL语法.而且他占的空间很小.大约只有160K,拥有快 ...

  8. Java笔记——数据库08

    目录 上集回顾 事务 2.1 为什么使用事务 2.2 事务的概念 事务的ACID特性 (原子性,持久性,隔离性,一致性) 并发事务:并发 . 并行 问题一 脏读 问题二: 不可重复读 2.3 事物的三 ...

  9. 将前台日期格式转成与数据库日期格式相对应,后台java转数据库日期格式

    前台到后台java时data日期类型的转化 在实体类中用@DataTimeFormat,这样设置即使传过来是空的字符串也是可以转的,要和前面传过来的格式一致,如 @XmlElement(name=&q ...

最新文章

  1. TensorRT 7.2.1 开发概要(下)
  2. python 事件通知模式_请问在 Python 的事件系统中,如何可以通过事件通知立刻终结一个正在运行的子线程?...
  3. java控制台输入空格输出后不显示_为撒我加上输入输出流的代码后控制台反而什么都不显示了呢?...
  4. 银河麒麟安装远程桌面
  5. 在Browser Application中使用XNA
  6. java redis 数据自过期_Java架构-Redis的内存回收策略和Key过期策略,看这篇就够了...
  7. 万兆网卡实际吞吐量_AKITIO 10G/NBASE-T PCIe 网卡开箱拆解评测
  8. 【BZOJ3238】差异,后缀数组+单调栈维护height
  9. String中的==与Empty
  10. Q96:过程纹理(Procedural Texture)(0)——概述
  11. 大数据分析对企业起到什么作用
  12. 红帽考试环境之RHCSA
  13. PPT素材模板哪个网站资源内容比较丰富?
  14. 能播放qlv格式的android软件,QLV用什么播放器 腾讯QLV转换MP4方法
  15. appcan中,地图插件调用百度导航
  16. 东芝和摩飞多功能锅到底哪一款值得拔草呢?本篇深度评测让你剁手不后悔;
  17. python基础分析_数据分析之Python基础
  18. Java设计模式面试题(一)
  19. Centos7 编译 php5.6出错
  20. 树莓派开机不加载桌面全屏启动chromium浏览器

热门文章

  1. 第一章 阿里大数据产品体系
  2. EasyPoi word导出教程
  3. 统计100以内能被7整除的自然数c语言,编写程序,计算1到100中既能被3整除又能被7整除的所有数,并计算这些数的个数...
  4. 2020-04-17
  5. pyScripter2.7 运行时提示远程解释器再初始化了
  6. Java 版植物大战僵尸思路和源码分享!
  7. matlab计算两向量的乘积,matlab中两个函数相乘
  8. 基于Android的家庭医生app
  9. PHP中Linux知识,超全面的Linux基础知识整理
  10. 华为机试 放苹果