Mybatis collection 递归查询并自动装填所有子节点(多参数查询传入参数方法)
需求:项目中想实现无限下拉子菜单功能,后台就需要返回包括子节点的所有数据
数据库表结构如下:
上次是通过在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 递归查询并自动装填所有子节点(多参数查询传入参数方法)相关推荐
- mysql树节点【所有子节点列表 and 查询所有父节点列表】
/**所有子节点列表*/ delimiter // CREATE FUNCTION `getChildList`(rootId varchar(100)) RETURNS varchar(2000) ...
- 查询结构树下的所有子节点包括要查询的节点
1.表设计 2.sql语句 select id_district from ( select *,if(find_in_set(parent_id, @pids) > 0, @pids ...
- SQL 语句递归查询 With AS 查找所有子节点
SQL 语句递归查询 With AS 查找所有子节点 create table #EnterPrise ( Department nvarchar(50),--部门名称 ParentDept ...
- Java递归查询某个节点下所有子节点多级信息(递归部门查询,递归树形结构数据查询)
前言 在做项目中我们会遇到树形结构数据,如果我们想要查询某个几点下面所有子节点(多级)数据,此时我们又不知道下面有多少级节点以及节点ID,那么我们就需要使用递归去查询了,当然在数据库中写函数也是可以实 ...
- mysql 递归查询所有子节点(子部门)返回id集合
一.导读 当我们查询所有的当前部门下以及当前部门下面的所有子部门,需要就需要我们获取所有当前节点和子节点的id,这里使用mysql的递归查询来实现.查找给定分类编码查找分类及其所有子类,包含子类的子类 ...
- mysql根据父节点递归查询所有子节点
mysql根据父节点递归查询所有子节点 在开发中,我们经常遇到通过父级节点查询所有子节点的需求,我们知道在mysql中我们可以自定义函数的方式来实现这个功能,但是自定义函数根据父节点递归查询所有子节点 ...
- oracle获取所有子节点,oracle递归查询所有子节点
Q4:Oracle通过递归查询父子兄弟节点方法示例 前言 说到Oracle中的递归查询语法,我觉得有一些数据库基础的童鞋应该都知道,做项目的时候应该也会用到,下面本文就来介绍下关于Oracle通过递归 ...
- mysql查找无根节点sql_SQL 双亲节点查找所有子节点的实现方法
怎么保存树状结构的数据呢?在 SQL 中常用的是双亲节点法.创建表如下 CREATE TABLE category ( id LONG, parentId LONG, name String(20) ...
- ztree之获取当前节点的所有子节点
在使用zTree插件实现树形图中,如果需要获取当前点击的父节点的子节点数的需求,可以使用treeNode.children获取子节点数据集合,使用length方法获取集合长度. 将当前节点的treeN ...
- js遍历树节点下的所有子节点_【数据结构与算法】(3)——树和二叉树
树 树的基本概念 树是一种非线性的数据结构,样子如图所示: 树的主要特点是树中的数据是分层存储的,每个元素称为树的节点,最顶层有且只有一个元素,称为根节点,其余层可以有任意数量的节点.除了根节点,其余 ...
最新文章
- how to force opened by browser
- 转 知道这20个正则表达式,能让你少写1,000行代码
- sed/awk与unix命令等价代码[转]
- 【虚拟化实战】Cluster设计之一资源池
- 列出所有K个元素的子集-----2013年1月26日
- linux开机自动启动开机日志,设置linux开机自动运行脚本
- ubuntu apache配置负载均衡篇(二)
- 模块使用:time、datetime、calendar、sys、os、os.path、normcase和normapath、random、json、pickle...
- 鸿蒙系统手机现在有什么,华为鸿蒙手机迟迟未来 手机操作系统面临的难点有哪些...
- php顺序查找法,php二分查找、顺序查找算法
- 追风猎洞只能喝西北风吗?
- 开源网络爬虫程序(spider)一览
- sopcast在ubuntu上的安装与使用
- 三网手机号码归属地查询小程序源码
- Windows 操作系统成功背后的传奇工程师
- 密码框password调用数字键盘
- 女子12楼坠下被11楼邻居一把抓住
- 什么是盒模型(标准盒模型,怪异盒模型)
- 51单片机的LCD12864电子秤设计
- QQ幻想杂食宠物各种前缀比较