前言
在工作中遇到需要对树状结构的数据进行一个处理,通过本文做出一个分享和总结。本文对数据的查询主要是通过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