需求:项目中想实现无限下拉子菜单功能,后台就需要返回包括子节点的所有数据

数据库表结构如下:

上次是通过在java程序中递归不断通过父级id查询子节点实现的:

https://blog.csdn.net/lianzhang861/article/details/83783796

但这样需要不断连接和断开数据库,比较费时

mybatis可以在数据库内部实现递归查询被自动装填,由于省去了数据库连接步骤,访问速度会更快,但会增加数据库服务器压力,使用时根据实际情况定使用程序递归还是数据库递归

方式是使用 resultMap中的collection,此标签可以一对多级联

<resultMap><constructor> //适用于不存在没有参数的构造方法<idArg></idArg><arg></arg></constructor><id/>//这个对象的主键<association/>//一对一级联<collection/>//一对多级联<discriminator>//鉴别器<case/></discriminator></resultMap>

实现方法:

1.首先添加该表的实体类ArticleCategory

public class ArticleCategory {private String categoryId;private String categoryName;private String categoryParentId;//存放子节点private List<ArticleCategory> subList;public String getCategoryId() {return categoryId;}public void setCategoryId(String categoryId) {this.categoryId = categoryId;}public String getCategoryName() {return categoryName;}public void setCategoryName(String categoryName) {this.categoryName = categoryName;}public List<ArticleCategory> getSubList() {return subList;}public void setSubList(List<ArticleCategory> subList) {this.subList = subList;}public String getCategoryParentId() {return categoryParentId;}public void setCategoryParentId(String categoryParentId) {this.categoryParentId = categoryParentId;}
}

2.controller调用

@ResponseBody
@RequestMapping(value = "getArticleCategoryTree2", produces = "text/plain;charset=UTF-8")
public String getArticleCategory2(@RequestParam Map<String,String> params) {RetBase ret=new RetBase();params.put("categoryId","0");//List<Map<String,Object>> list=this.getSubCategory(params);List<ArticleCategory> list=articleService.getArticleCategory1(params);ret.setData(list);ret.setSuccess(true);return JSON.toJSONString(ret);
}

3.dao

public List<Map<String,Object>> getArticleCategory(Map<String,String> params);

4.xml

<resultMap id="Category" type="com.zhuhuixin.common.entity.ArticleCategory"><id column="category_id" property="categoryId"/><result column="category_name" property="categoryName"></result><result column="category_parent_id" property="categoryParentId"></result><collection column="category_id" property="subList"ofType="com.zhuhuixin.common.entity.ArticleCategory"select="getArticleCategory"></collection>
</resultMap><select id="getArticleCategory" resultMap="Category">select*from article_category twhere  t.category_status='YES'and t.category_parent_id = #{categoryId}order by t.category_name
</select>

5.查出的数据格式

注意:

1.collection 的column与id的column相同,property为实体类中子集合的名字,select与查询方法名字相同

2.查询时一定要将id和parentId都查出来,否则mybaits无法完成递归,我用*查就更没问题了。实体类中也要有父id那个属性

3.我从controller调用的时候已经传入了一个父id参数,然后mybatis递归时又自动将父id传给查询。但这个参数的名字可以和resultMap中的id名字不相同,也就是说如果我controller里面传的父id名字为 cc,select中改为

and t.category_parent_id = #{cc}

mybatis照样能查出子集合,所以这个参数名可以随便写

不过前台js解读数据的时候也得用递归方法解析数据,有点麻烦~~~

========== 华丽分割线 ==============

时间来到了2019.12.19

最近搞springboot项目中的菜单管理中又用到了这个,不过菜单由于有权限限制啥的,传入的参数比较多,查询就会出现问题,要不查不出来,要不就是子查询参数不生效,因为先前只用到一个父id参数,而且网上能找到的大部分例子都是一个参数例子,这次经过试验总结到collection多参数传入的方法

<resultMap><id/>//这个对象的主键<collection column=" {menuParent=MENU_ID,menuType=MENU_TYPE,menuStatus=MENU_STATUS,userId=USER_ID}" property="subList"ofType="com.bomc.enterprise.entry.SysMenu"select="getMenuList"></collection></resultMap>

首先collection是用来递归查询一对多的,其次是参数传入的问题,column是用来传参数的,如果只有一个参数,直接写一个用来关联的字段名就行了,不管你传的参数叫啥,它都会把上次查出的结果的这个字段自动放到下一次查询 这个参数的位置,所以就会发现如果只有一个参数,你参数传啥名字都没事。

<resultMap id="Category" type="com.zhuhuixin.common.entity.ArticleCategory"><id column="category_id" property="categoryId"/><result column="category_name" property="categoryName"></result><result column="category_parent_id" property="categoryParentId"></result><collection column="category_id" property="subList"ofType="com.zhuhuixin.common.entity.ArticleCategory"select="getArticleCategory"></collection>
</resultMap><select id="getArticleCategory" resultMap="Category">select*from article_category twhere  t.category_status='YES'and t.category_parent_id = #{categoryId}order by t.category_name
</select>

但如果你的查询有多个参数就不一样了,需要用这种写法了,前面是传入参数名,等号 后面是字段名字

<collection column=" {menuParent=MENU_ID,menuType=MENU_TYPE,menuStatus=MENU_STATUS,userId=USER_ID}" 

例子:

1.传入的参数

params.put("menuParent", "0");
params.put("menuType", "menu");
params.put("userId", USER.getUserId());
List<SysMenu> menuList = menuService.getMenuList(params);

2.xml

<resultMap id="SysMenu" type="com.bomc.enterprise.entry.SysMenu" ><id column="MENU_ID" property="menuId"/><!--<result column="MENU_ID" property="menuId" jdbcType="VARCHAR" />--><result column="MENU_PARENT" property="menuParent" jdbcType="VARCHAR" /><result column="MENU_CODE" property="menuCode" jdbcType="VARCHAR" /><result column="MENU_NAME" property="menuName" jdbcType="VARCHAR" /><result column="MENU_TYPE" property="menuType" jdbcType="VARCHAR" /><result column="MENU_LEAF" property="menuLeaf" jdbcType="VARCHAR" /><result column="MENU_METHOD" property="menuMethod" jdbcType="VARCHAR" /><result column="MENU_ICON" property="menuIcon" jdbcType="VARCHAR" /><result column="MENU_URL" property="menuUrl" jdbcType="VARCHAR" /><result column="MENU_DESC" property="menuDesc" jdbcType="VARCHAR" /><result column="MENU_STATUS" property="menuStatus" jdbcType="VARCHAR" /><result column="MENU_SORT" property="menuSort" jdbcType="DECIMAL" /><result column="CREATE_TIME" property="createTime" jdbcType="DATE" /><result column="MODIFY_TIME" property="modifyTime" jdbcType="DATE" /><result column="AVAILABLE_START_TIME" property="availableStartTime" jdbcType="DATE" /><result column="AVAILABLE_END_TIME" property="availableEndTime" jdbcType="DATE" /><collection column="{menuParent=MENU_ID,menuType=MENU_TYPE,userId=USER_ID}" property="subList"ofType="com.bomc.enterprise.entry.SysMenu"select="getMenuList"></collection>
</resultMap><select id="getMenuList" resultMap="SysMenu">selectt.*,case t.menu_type when 'menu' then '按钮' when 'href' then '链接' else '菜单' end as menu_type1,case t.menu_status when 'YES' then '是' else '否' end as menu_status1,#{userId,jdbcType=VARCHAR} USER_IDfrom sys_menu twhere1=1<if test="menuParent!=null and menuParent!=''">and t.menu_parent =#{menuParent,jdbcType=VARCHAR}</if><choose><when test="menuStatus!=null and menuStatus!=''">and t.menu_status=#{menuStatus,jdbcType=VARCHAR}</when><otherwise>and t.menu_status='1'</otherwise></choose><if test="menuType!=null and menuType!=''">and t.menu_type = #{menuType,jdbcType=VARCHAR}</if><if test="menuName!=null and menuName!=''">and t.menu_name like '%'||#{menuName,jdbcType=VARCHAR}||'%'</if><if test="roleId!=null and roleId!=''">and t.menu_Id in (select t1.menu_Id from sys_role_menu t1where t1.role_id = #{roleId,jdbcType=VARCHAR})</if><if test="userId!=null and userId!=''">and t.menu_Id in (select t1.menu_Id from sys_role_menu t1where t1.role_id in(select t2.role_id from sys_user_role t2where t2.user_id = #{userId,jdbcType=VARCHAR}))</if>order by t.menu_sort</select>

上面例子我传入了三个参数,想要正常查询,就得在column中配置三个参数,虽然我的sql中还判断其他的参数,但实际没有用到的话就不必在column中配

每次查询到父级后就会把查到结果中对应的字段值 匹配 配置的 参数名,一一对应的设置为下一次查询的参数值。

这也就意味着你的参数必须存在于上一次的查询结果集中,但是对于菜单管理,需要传入userId 去查询菜单权限这种情况,菜单表中肯定没有userId这个字段,这就需要你在查询第一次的时候就手动加上这个字段:

按理说应该在实体类和resultMap映射也添加这个字段才对,但我测试的是即使 实体类和resultMap映射中没有这个字段也可以正常使用。

如果参数是常量似乎可以直接写,但是不能直接把#{参数}放到column中:

column="{menuParent=MENU_ID,menuType=MENU_TYPE,userId='111'}"

总之多参数传入这么可以解决,暂时还没发现有啥正统的解决方法,其次关于是否分页有问题还没有测试,暂时先这样

Mybatis collection 递归查询并自动装填所有子节点(多参数查询传入参数方法)相关推荐

  1. mysql树节点【所有子节点列表 and 查询所有父节点列表】

    /**所有子节点列表*/ delimiter // CREATE FUNCTION `getChildList`(rootId varchar(100)) RETURNS varchar(2000) ...

  2. 查询结构树下的所有子节点包括要查询的节点

    1.表设计 2.sql语句 select id_district from (     select *,if(find_in_set(parent_id, @pids) > 0, @pids ...

  3. SQL 语句递归查询 With AS 查找所有子节点

    SQL 语句递归查询 With AS 查找所有子节点 create table #EnterPrise (   Department nvarchar(50),--部门名称   ParentDept  ...

  4. Java递归查询某个节点下所有子节点多级信息(递归部门查询,递归树形结构数据查询)

    前言 在做项目中我们会遇到树形结构数据,如果我们想要查询某个几点下面所有子节点(多级)数据,此时我们又不知道下面有多少级节点以及节点ID,那么我们就需要使用递归去查询了,当然在数据库中写函数也是可以实 ...

  5. mysql 递归查询所有子节点(子部门)返回id集合

    一.导读 当我们查询所有的当前部门下以及当前部门下面的所有子部门,需要就需要我们获取所有当前节点和子节点的id,这里使用mysql的递归查询来实现.查找给定分类编码查找分类及其所有子类,包含子类的子类 ...

  6. mysql根据父节点递归查询所有子节点

    mysql根据父节点递归查询所有子节点 在开发中,我们经常遇到通过父级节点查询所有子节点的需求,我们知道在mysql中我们可以自定义函数的方式来实现这个功能,但是自定义函数根据父节点递归查询所有子节点 ...

  7. oracle获取所有子节点,oracle递归查询所有子节点

    Q4:Oracle通过递归查询父子兄弟节点方法示例 前言 说到Oracle中的递归查询语法,我觉得有一些数据库基础的童鞋应该都知道,做项目的时候应该也会用到,下面本文就来介绍下关于Oracle通过递归 ...

  8. mysql查找无根节点sql_SQL 双亲节点查找所有子节点的实现方法

    怎么保存树状结构的数据呢?在 SQL 中常用的是双亲节点法.创建表如下 CREATE TABLE category ( id LONG, parentId LONG, name String(20) ...

  9. ztree之获取当前节点的所有子节点

    在使用zTree插件实现树形图中,如果需要获取当前点击的父节点的子节点数的需求,可以使用treeNode.children获取子节点数据集合,使用length方法获取集合长度. 将当前节点的treeN ...

  10. js遍历树节点下的所有子节点_【数据结构与算法】(3)——树和二叉树

    树 树的基本概念 树是一种非线性的数据结构,样子如图所示: 树的主要特点是树中的数据是分层存储的,每个元素称为树的节点,最顶层有且只有一个元素,称为根节点,其余层可以有任意数量的节点.除了根节点,其余 ...

最新文章

  1. how to force opened by browser
  2. 转 知道这20个正则表达式,能让你少写1,000行代码
  3. sed/awk与unix命令等价代码[转]
  4. 【虚拟化实战】Cluster设计之一资源池
  5. 列出所有K个元素的子集-----2013年1月26日
  6. linux开机自动启动开机日志,设置linux开机自动运行脚本
  7. ubuntu apache配置负载均衡篇(二)
  8. 模块使用:time、datetime、calendar、sys、os、os.path、normcase和normapath、random、json、pickle...
  9. 鸿蒙系统手机现在有什么,华为鸿蒙手机迟迟未来 手机操作系统面临的难点有哪些...
  10. php顺序查找法,php二分查找、顺序查找算法
  11. 追风猎洞只能喝西北风吗?
  12. 开源网络爬虫程序(spider)一览
  13. sopcast在ubuntu上的安装与使用
  14. 三网手机号码归属地查询小程序源码
  15. Windows 操作系统成功背后的传奇工程师
  16. 密码框password调用数字键盘
  17. 女子12楼坠下被11楼邻居一把抓住
  18. 什么是盒模型(标准盒模型,怪异盒模型)
  19. 51单片机的LCD12864电子秤设计
  20. QQ幻想杂食宠物各种前缀比较

热门文章

  1. 为什么大学没有前端课程?
  2. 用HOOK机制让自绘菜单栏控件模拟系统菜单栏行为
  3. 蓝色配色灵感 | 解读蓝色
  4. 怎样批量修改图片尺寸?
  5. 关于购买域名的一些建议
  6. 通信教程 | USB、HDMI、DP接口及速度
  7. 转正述职报告怎么写?五年经验PM告诉你……
  8. ai面试的优缺点_被AI程序面试是一种怎样的体验?该如何准备!!!
  9. Python:计算KDJ指标
  10. Labview的CAN通讯