Mybatis递归查询实践

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6


在我们开发企业应用时,有这样一种常见的业务场景:
有一张数据库表,里面保存着所有的报表(也可以是其它实体)与报表分类,表的关键列如下所示:

列名

含义

id

主键

name

报表名称或分类名称

pid

父ID,当父ID为null时为顶级目录

由于分类是可以无限层级的(实际上不超过10层),因此该表实际上存储的是一个树结构,即一个目录下面可以有多个目录或报表,类似于操作系统的文件系统

现有如下问题:当我们已知报表ID时,如果查找该报表上面的所有层级目录?
首先依靠一条SQL是很难查询出来的,因为前面已经讲过层级是可以无限扩展的。
其次,利用service层代码递归执行SQL查询语句肯定是可以的。
伪SQL如下:

select id,name,pid from report_tree where id=#{pid})

将每一次查到的pid作为下一次查询的id,直到查不出来结果为止。

但本文要介绍一种更优雅的方式:利用Mybatis框架的递归查询。
下面直接上代码。
实体:

public class ReportTree {
    private Integer id;
    private String name;
    private String pid;
    private ReportTree parent;
	// 省略getter/setter方法
}

Mapper层:

public interface ReportTreeMapper {
    List<ReportTree> selectTree(ReportTree reportTree);
    List<ReportTree> selectTreeByPid(String pid);
}

Mapper.xml:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.bobo.dao.ReportTreeMapper" >
  <resultMap id="treeResultMap" type="com.bobo.domain.ReportTree">
    <id column="id" property="id"/>
    <result column="name" property="name"/>
    <result column="pid" property="pid"/>
    <association property="parent" column="pid" select="selectTreeByPid"></association>
  </resultMap>

  <select id="selectTree" resultMap="treeResultMap">
    select * from report_tree
    <where>
      <if test="null != id">
        id= #{id}
      </if>
    </where>
  </select>

  <select id="selectTreeByPid" resultMap="treeResultMap">
    select * from report_tree where id=#{pid}
  </select>
</mapper>

调用方式:

List<ReportTree> reportTreeList = reportTreeMapper.selectTree(ReportTree.builder().id("报表ID").build());

如此,就能得到我们想要的结果了。
Mybatis递归查询最重要的一个点是resultMap下面的association标签。下面解释一下association标签各属性的含义。
association标签表示一对一的关联关系,Mybatis会执行association的select属性关联的查询语句并将结果映射给实体的parent字段。
association的column属性的值为一个或多个(逗号分隔)实体的字段,Mybatis会将column中实体字段作为参数传给association的select属性关联的查询语句,如此一来就形成了递归查询关系。


阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6