JAVA树状结构数据处理

本文介绍了如何使用MyBatis的级联查询和ResultMap在XML中构建树状结构数据,包括数据库结构、查询步骤以及在VO中处理数据的方法。通过级联查询和VO的set方法,可以高效地处理和组装树形结构,避免了多次循环和递归。同时,展示了如何插入叶子节点和整合不同数据源的信息。
摘要由CSDN通过智能技术生成


前言

在工作中遇到需要对树状结构的数据进行一个处理,通过本文做出一个分享和总结。本文对数据的查询主要是通过MyBatis在xml文件中使用resultMap标签来实现对数据的循环查询,并且通过返回值映射到VO中,通过VO中set方法的处理直接生成一个树状对象。


一、数据库中的结构

在这里插入图片描述
要处理的对象在数据库中大致是这样的格式,并未用到一个记录父级完整路径的一个键。
例如:
在这里插入图片描述
若数据库中加了一个用来记录父级id的一个键,要查询二级分类及二级分类的所有下级分类则只需要对parent_order这个键进行模糊查询即可。

二、查询步骤

项目结构都差不多就不在这里赘述了,直接mapper类对应xml中的sql语句直接调用就是了。

1.XML

代码如下(示例):(下列代码只作参考,我没跑过的不一定对,大致结构是没有错的)

   <resultMap id="studyMainTree" type="com.cataloguemanage.business.entity.AVO">
        <result column="id" property="id" javaType="String"/>
        <result column="parentId" property="parentId" javaType="String"/>
        <result column="name" property="name" javaType="String"/>   
        <collection column="id" property="children" select="getChildrenByPid"
					ofType="com.cataloguemanage.business.entity.AVO"/>
    </resultMap>
    
    <select id="queryClassify" resultMap="studyMainTree">
        SELECT
        id ,
        parent_id parentId ,
        name 
        FROM tableA 
        WHERE parent_id ='0'
    </select>
    
    <select id="getChildrenByPid" resultMap="studyMainTree">
        SELECT
        id ,
        parent_id  parentId ,
        name 
        FROM tableB 
        WHERE parent_id =#{id} 
    </select>

queryClassify就是这个级联查询的入口 queryClassify执行一次 getChildrenByPid执行多次

2.VO

代码如下(示例):联系上图中的AVO,使用AVO来接受查询到的数据

@Data
public class AVO  {
	private String id;

	private String name;
	
	private String parentId;

    public List<AVO> getChildren() {
        return children;
    }

    public void setChildren(List<CatalogClassifyVO> children) {
        if (children!= null && !children.isEmpty()) {
        	//相应的业务逻辑
           this.children=children;
           }
    }

    //子分类
    private List<AVO> children;
}

在VO中我们能通过在set方法中添加相应的业务逻辑,比如统计子分类的数量、整合某些字段等等,但所生成的树对象是单向的,只能从父找到子。父与子的联系都在setChildren方法中,并且是以类似递归一样从最下级的set方法开始执行。

3.树中插入叶子

在resultMap中再添加一个collection,并在VO中添加接受对应对象的成员。能实现对不同数据结构的对象进行查询,并组合成一个树状结构。
XML

 <resultMap id="resourceList" type="com.cataloguemanage.business.entity.AVO">
        <result column="classifyCode" property="classifyCode" javaType="String"/>
        <collection column="classifyCode" property="children" select="selectCatalogueChildren"
                    ofType="com.cataloguemanage.business.entity.AVO"/>
        <collection column="classifyCode" property="resource" select="selectResourceByresourceCode"
                    ofType="java.util.Map"/>
    </resultMap>
    <select id="selectCatalogueInfo" resultMap="resourceList">
        SELECT
        a.classify_code classifyCode
        from
        table a
        where
        a.classify_code=#{classifyCode} 
    </select>
    <select id="selectCatalogueChildren" resultMap="resourceList">
         SELECT
        a.classify_code classifyCode
        from
        catalog_classify a
        WHERE
        a.parent_id=#{classifyCode} 
    </select>
    <select id="selectResourceByResourceCode" resultType="java.util.Map">
        select
        b.resource_code resourceCode,
        b.resource_name label
        from tableA a left join tableB b
        on b.resource_code = a.resource_classify_code
        where 
        and a.classify_code = #{classifyCode}
    </select>

VO

   private List<BVO> resource =new ArrayList<>();
    
   public void setResource(List<BVO> resource) {
        if(resource !=null&&!resource.isEmpty()){
            this.resource.addAll(resource);
        }
    }

总结

用映射来处理树状结构的数据是非常清晰的,不需要查询出所有数据来用多个for循环来进行遍历和数据组装。使用级联查询还是非常灵活的,例如能携带多个参数到子查询中实现树的模糊查询、在set方法中将所有的子整合成一个集合等等。在级联过程中,只有一个SqlSession,所以说在绝大部门情况下,使用级联查询树状结构的数据是比在代码中用递归的方式查询效率要高。
第一次做分享,有问题请见谅。
企鹅:747870530

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
$(function(){ $.fn.extend({ SimpleTree:function(options){ //初始化参数 var option = $.extend({ click:function(a){ } },options); option.tree=this; /* 在参数对象中添加对当前菜单树的引用,以便在对象中使用该菜单树 */ option._init=function(){ /* * 初始化菜单展开状态,以及分叉节点的样式 */ this.tree.find("ul ul").hide(); /* 隐藏所有子级菜单 */ this.tree.find("ul ul").prev("li").removeClass("open"); /* 移除所有子级菜单父节点的 open 样式 */ this.tree.find("ul ul[show='true']").show(); /* 显示 show 属性为 true 的子级菜单 */ this.tree.find("ul ul[show='true']").prev("li").addClass("open"); /* 添加 show 属性为 true 的子级菜单父节点的 open 样式 */ }/* option._init() End */ /* 设置所有超链接不响应单击事件 */ this.find("a").click(function(){ $(this).parent("li").click(); return false; }); /* 菜单项 接受单击 */ this.find("li").click(function(){ /* * 当单击菜单项 * 1.触发用户自定义的单击事件,将该 标签中的第一个超链接做为参数传递过去 * 2.修改当前菜单项所属的子菜单的显示状态(如果等于 true 将其设置为 false,否则将其设置为 true) * 3.重新初始化菜单 */ option.click($(this).find("a")[0]); /* 触发单击 */ /* * 如果当前节点下面包含子菜单,并且其 show 属性的值为 true,则修改其 show 属性为 false * 否则修改其 show 属性为 true */ /* if($(this).next("ul").attr("show")=="true"){ $(this).next("ul").attr("show","false"); }else{ $(this).next("ul").attr("show","true"); }*/ /* 初始化菜单 */ option._init(); }); /* 设置所有父节点样式 */ this.find("ul").prev("li").addClass("folder"); /* 设置节点“是否包含子节点”属性 */ this.find("li").find("a").attr("hasChild",false); this.find("ul").prev("li").find("a").attr("hasChild",true); /* 初始化菜单 */ option._init(); }/* SimpleTree Function End */ }); });
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值