树形表,自关联表查询技巧

方法一:部门表,部门表中除了自身主键id外,还有另一个字段parentId父id,可以一直递归下去

数据库表: 

菜单这样展示就需要我们在接口的返回值中,返回这样的层级数据:

[
  {
    "id": 1,
    "name": "股东会",
    "parentId": -1,
    "depPath": ".1",
    "enabled": true,
    "isParent": true,
    "children": [
      {
        "id": 2,
        "name": "董事会",
        "parentId": 1,
        "depPath": ".1.2",
        "enabled": true,
        "isParent": true,
        "children": [
          {
            "id": 3,
            "name": "总办",
            "parentId": 2,
            "depPath": ".1.2.3",
            "enabled": true,
            "isParent": true,
            "children": [
              {
                "id": 4,
                "name": "财务部",
                "parentId": 3,
                "depPath": ".1.2.3.4",
                "enabled": true,
                "isParent": false,
                "children": [],
                "result": null
              },
              {
                "id": 5,
                "name": "市场部",
                "parentId": 3,
                "depPath": ".1.2.3.5",
                "enabled": true,
                "isParent": true,
                "children": [
                  {
                    "id": 6,
                    "name": "华东市场部",
                    "parentId": 5,
                    "depPath": "1.2.3.5.6",
                    "enabled": true,
                    "isParent": true,
                    "children": [
                      {
                        "id": 8,
                        "name": "上海市场部",
                        "parentId": 6,
                        "depPath": "1.2.3.5.6.8",
                        "enabled": true,
                        "isParent": false,
                        "children": [],
                        "result": null
                      }
                    ],
                    "result": null
                  },
                  {
                    "id": 7,
                    "name": "华南市场部",
                    "parentId": 5,
                    "depPath": "1.2.3.5.7",
                    "enabled": true,
                    "isParent": false,
                    "children": [],
                    "result": null
                  },
                  {
                    "id": 9,
                    "name": "西北市场部",
                    "parentId": 5,
                    "depPath": ".1.2.3.5.9",
                    "enabled": true,
                    "isParent": true,
                    "children": [
                      {
                        "id": 10,
                        "name": "贵阳市场",
                        "parentId": 9,
                        "depPath": ".1.2.3.5.9.10",
                        "enabled": true,
                        "isParent": true,
                        "children": [
                          {
                            "id": 11,
                            "name": "乌当区市场",
                            "parentId": 10,
                            "depPath": ".1.2.3.5.9.10.11",
                            "enabled": true,
                            "isParent": false,
                            "children": [],
                            "result": null
                          }
                        ],
                        "result": null
                      }
                    ],
                    "result": null
                  }
                ],
                "result": null
              },
              {
                "id": 12,
                "name": "技术部",
                "parentId": 3,
                "depPath": ".1.2.3.12",
                "enabled": true,
                "isParent": false,
                "children": [],
                "result": null
              },
              {
                "id": 13,
                "name": "运维部",
                "parentId": 3,
                "depPath": ".1.2.3.13",
                "enabled": true,
                "isParent": true,
                "children": [
                  {
                    "id": 149,
                    "name": "测试部门1",
                    "parentId": 13,
                    "depPath": ".1.2.3.13.149",
                    "enabled": true,
                    "isParent": false,
                    "children": [],
                    "result": null
                  }
                ],
                "result": null
              }
            ],
            "result": null
          }
        ],
        "result": null
      }
    ],
    "result": null
  }
]

返回这样的数据:其中有个简单的方法

1: 修改数据库表对应的实体类,给实体类添加一个字段 children

@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("t_department")
@ApiModel(value="Department对象", description="")
public class Department implements Serializable {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "id")
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;

    @ApiModelProperty(value = "部门名称")
    private String name;

    @ApiModelProperty(value = "父id")
    private Integer parentId;

    @ApiModelProperty(value = "路径")
    private String depPath;

    @ApiModelProperty(value = "是否启用")
    private Boolean enabled;

    @ApiModelProperty(value = "是否上级")
    private Boolean isParent;

    @ApiModelProperty(value = "子部门列表")
    @TableField(exist = false)
    private List<Department> children;

    @ApiModelProperty(value = "返回结果,存储过程使用")
    @TableField(exist = false)
    private Integer result;

}

2. 正常的写Controlelr,service,下面给出ServiceImpl后面的代码

ServiceImpl.java

这里-1是 顶级节点的parentId为-1

    /**
     * 获取所有部门
     * @return
     */
    @Override
    public List<Department> getAllDepartments() {
        return departmentMapper.getAllDepartments(-1);
    }

Mapper.java

    /**
     * 获取所有部门
     * @return
     */
    List<Department> getAllDepartments(Integer parentId);

Mapper.xml

定义一个返回的Map,在这个Map中,通过collection标签的 select 属性,来给这个集合赋值,每次赋值就再调用一下 getAllDepartments方法查询一次,携带的参数为第一次查询时候的主键id

    <!--获取所有部门-->
    <select id="getAllDepartments" resultMap="DepartmentWithChildren" parameterType="Integer">
        select
        <include refid="Base_Column_List" />
        from t_department
        where parentId = #{parentId}
    </select>


     <resultMap id="DepartmentWithChildren" type="com.example.pojo.Department" extends="BaseResultMap">
        <!--select 相当是拿到children,如何拿到值呢,那就再调用一下这个方法,传id-->
        <collection property="children" ofType="com.example.pojo.Department" select="com.example.mapper.DepartmentMapper.getAllDepartments" column="id">
        </collection>
    </resultMap>

    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List">
        id, name, parentId, depPath, enabled, isParent
    </sql>

 方法二: 通过sql关联查询

比如 二级树,左侧的菜单查询

查询出来是这样的:

 

数据库表:

 

返回的数据格式是这样的:

[
  {
    "id": 2,
    "url": "/",
    "path": "/home",
    "component": "Home",
    "name": "员工资料",
    "iconCls": "fa fa-user-circle-o",
    "keepAlive": null,
    "requireAuth": true,
    "parentId": 1,
    "enabled": true,
    "children": [
      {
        "id": 7,
        "url": "/employee/basic/**",
        "path": "/emp/basic",
        "component": "EmpBasic",
        "name": "基本资料",
        "iconCls": null,
        "keepAlive": null,
        "requireAuth": true,
        "parentId": 2,
        "enabled": true,
        "children": null,
        "roles": null
      }
    ],
    "roles": null
  },
  {
    "id": 3,
    "url": "/",
    "path": "/home",
    "component": "Home",
    "name": "人事管理",
    "iconCls": "fa fa-address-card-o",
    "keepAlive": null,
    "requireAuth": true,
    "parentId": 1,
    "enabled": true,
    "children": [
      {
        "id": 9,
        "url": "/personnel/emp/**",
        "path": "/per/emp",
        "component": "PerEmp",
        "name": "员工资料",
        "iconCls": null,
        "keepAlive": null,
        "requireAuth": true,
        "parentId": 3,
        "enabled": true,
        "children": null,
        "roles": null
      },
      {
        "id": 10,
        "url": "/personnel/ec/**",
        "path": "/per/ec",
        "component": "PerEc",
        "name": "员工奖惩",
        "iconCls": null,
        "keepAlive": null,
        "requireAuth": true,
        "parentId": 3,
        "enabled": true,
        "children": null,
        "roles": null
      },
      {
        "id": 11,
        "url": "/personnel/train/**",
        "path": "/per/train",
        "component": "PerTrain",
        "name": "员工培训",
        "iconCls": null,
        "keepAlive": null,
        "requireAuth": true,
        "parentId": 3,
        "enabled": true,
        "children": null,
        "roles": null
      },
      {
        "id": 12,
        "url": "/personnel/salary/**",
        "path": "/per/salary",
        "component": "PerSalary",
        "name": "员工调薪",
        "iconCls": null,
        "keepAlive": null,
        "requireAuth": true,
        "parentId": 3,
        "enabled": true,
        "children": null,
        "roles": null
      },
      {
        "id": 13,
        "url": "/personnel/remove/**",
        "path": "/per/mv",
        "component": "PerMv",
        "name": "员工调动",
        "iconCls": null,
        "keepAlive": null,
        "requireAuth": true,
        "parentId": 3,
        "enabled": true,
        "children": null,
        "roles": null
      }
    ],
    "roles": null
  },
  {
    "id": 4,
    "url": "/",
    "path": "/home",
    "component": "Home",
    "name": "薪资管理",
    "iconCls": "fa fa-money",
    "keepAlive": null,
    "requireAuth": true,
    "parentId": 1,
    "enabled": true,
    "children": [
      {
        "id": 14,
        "url": "/salary/sob/**",
        "path": "/sal/sob",
        "component": "SalSob",
        "name": "工资账套管理",
        "iconCls": null,
        "keepAlive": null,
        "requireAuth": true,
        "parentId": 4,
        "enabled": true,
        "children": null,
        "roles": null
      },
      {
        "id": 15,
        "url": "/salary/sobcfg/**",
        "path": "/sal/sobcfg",
        "component": "SalSobCfg",
        "name": "员工账套设置",
        "iconCls": null,
        "keepAlive": null,
        "requireAuth": true,
        "parentId": 4,
        "enabled": true,
        "children": null,
        "roles": null
      },
      {
        "id": 16,
        "url": "/salary/table/**",
        "path": "/sal/table",
        "component": "SalTable",
        "name": "工资表管理",
        "iconCls": null,
        "keepAlive": null,
        "requireAuth": true,
        "parentId": 4,
        "enabled": true,
        "children": null,
        "roles": null
      },
      {
        "id": 17,
        "url": "/salary/month/**",
        "path": "/sal/month",
        "component": "SalMonth",
        "name": "月末处理",
        "iconCls": null,
        "keepAlive": null,
        "requireAuth": true,
        "parentId": 4,
        "enabled": true,
        "children": null,
        "roles": null
      },
      {
        "id": 18,
        "url": "/salary/search/**",
        "path": "/sal/search",
        "component": "SalSearch",
        "name": "工资表查询",
        "iconCls": null,
        "keepAlive": null,
        "requireAuth": true,
        "parentId": 4,
        "enabled": true,
        "children": null,
        "roles": null
      }
    ],
    "roles": null
  },
  {
    "id": 5,
    "url": "/",
    "path": "/home",
    "component": "Home",
    "name": "统计管理",
    "iconCls": "fa fa-bar-chart",
    "keepAlive": null,
    "requireAuth": true,
    "parentId": 1,
    "enabled": true,
    "children": [
      {
        "id": 19,
        "url": "/statistics/all/**",
        "path": "/sta/all",
        "component": "StaAll",
        "name": "综合信息统计",
        "iconCls": null,
        "keepAlive": null,
        "requireAuth": true,
        "parentId": 5,
        "enabled": true,
        "children": null,
        "roles": null
      },
      {
        "id": 20,
        "url": "/statistics/score/**",
        "path": "/sta/score",
        "component": "StaScore",
        "name": "员工积分统计",
        "iconCls": null,
        "keepAlive": null,
        "requireAuth": true,
        "parentId": 5,
        "enabled": true,
        "children": null,
        "roles": null
      },
      {
        "id": 21,
        "url": "/statistics/personnel/**",
        "path": "/sta/pers",
        "component": "StaPers",
        "name": "人事信息统计",
        "iconCls": null,
        "keepAlive": null,
        "requireAuth": true,
        "parentId": 5,
        "enabled": true,
        "children": null,
        "roles": null
      },
      {
        "id": 22,
        "url": "/statistics/recored/**",
        "path": "/sta/record",
        "component": "StaRecord",
        "name": "人事记录统计",
        "iconCls": null,
        "keepAlive": null,
        "requireAuth": true,
        "parentId": 5,
        "enabled": true,
        "children": null,
        "roles": null
      }
    ],
    "roles": null
  },
  {
    "id": 6,
    "url": "/",
    "path": "/home",
    "component": "Home",
    "name": "系统管理",
    "iconCls": "fa fa-windows",
    "keepAlive": null,
    "requireAuth": true,
    "parentId": 1,
    "enabled": true,
    "children": [
      {
        "id": 23,
        "url": "/system/basic/**",
        "path": "/sys/basic",
        "component": "SysBasic",
        "name": "基础信息设置",
        "iconCls": null,
        "keepAlive": null,
        "requireAuth": true,
        "parentId": 6,
        "enabled": true,
        "children": null,
        "roles": null
      },
      {
        "id": 24,
        "url": "/system/cfg/**",
        "path": "/sys/cfg",
        "component": "SysCfg",
        "name": "系统管理",
        "iconCls": null,
        "keepAlive": null,
        "requireAuth": true,
        "parentId": 6,
        "enabled": true,
        "children": null,
        "roles": null
      },
      {
        "id": 25,
        "url": "/system/log/**",
        "path": "/sys/log",
        "component": "SysLog",
        "name": "操作日志管理",
        "iconCls": null,
        "keepAlive": null,
        "requireAuth": true,
        "parentId": 6,
        "enabled": true,
        "children": null,
        "roles": null
      },
      {
        "id": 26,
        "url": "/system/admin/**",
        "path": "/sys/admin",
        "component": "SysAdmin",
        "name": "操作员管理",
        "iconCls": null,
        "keepAlive": null,
        "requireAuth": true,
        "parentId": 6,
        "enabled": true,
        "children": null,
        "roles": null
      },
      {
        "id": 27,
        "url": "/system/data/**",
        "path": "/sys/data",
        "component": "SysData",
        "name": "备份恢复数据库",
        "iconCls": null,
        "keepAlive": null,
        "requireAuth": true,
        "parentId": 6,
        "enabled": true,
        "children": null,
        "roles": null
      },
      {
        "id": 28,
        "url": "/system/init/**",
        "path": "/sys/init",
        "component": "SysInit",
        "name": "初始化数据库",
        "iconCls": null,
        "keepAlive": null,
        "requireAuth": true,
        "parentId": 6,
        "enabled": true,
        "children": null,
        "roles": null
      }
    ],
    "roles": null
  }
]

对应的返回实体类:

@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("t_menu")
@ApiModel(value="Menu对象", description="")
public class Menu implements Serializable {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "id")
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;

    @ApiModelProperty(value = "url")
    private String url;

    @ApiModelProperty(value = "path")
    private String path;

    @ApiModelProperty(value = "组件")
    private String component;

    @ApiModelProperty(value = "菜单名")
    private String name;

    @ApiModelProperty(value = "图标")
    private String iconCls;

    @ApiModelProperty(value = "是否保持激活")
    private Boolean keepAlive;

    @ApiModelProperty(value = "是否要求权限")
    private Boolean requireAuth;

    @ApiModelProperty(value = "父id")
    private Integer parentId;

    @ApiModelProperty(value = "是否启用")
    private Boolean enabled;

    @ApiModelProperty(value = "子菜单")
    @TableField(exist = false) // 告诉mybatisplus这个字段不在表中,查询的时候不要去查
    private List<Menu> children;

    @ApiModelProperty(value = "角色列表")
    @TableField(exist = false)
    private List<Role> roles;

}

mapper:

    List<Menu> getMenuByAdminId(Integer id);

mapper.xml

    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.example.pojo.Menu">
        <id column="id" property="id" />
        <result column="url" property="url" />
        <result column="path" property="path" />
        <result column="component" property="component" />
        <result column="name" property="name" />
        <result column="iconCls" property="iconCls" />
        <result column="keepAlive" property="keepAlive" />
        <result column="requireAuth" property="requireAuth" />
        <result column="parentId" property="parentId" />
        <result column="enabled" property="enabled" />
    </resultMap>

    <resultMap id="Menus" type="com.example.pojo.Menu" extends="BaseResultMap">
        <!--子分类菜单   property:属性-->
        <collection property="children" ofType="com.example.pojo.Menu">
            <id column="id2" property="id" />
            <result column="url2" property="url" />
            <result column="path2" property="path" />
            <result column="component2" property="component" />
            <result column="name2" property="name" />
            <result column="iconCls2" property="iconCls" />
            <result column="keepAlive2" property="keepAlive" />
            <result column="requireAuth2" property="requireAuth" />
            <result column="parentId2" property="parentId" />
            <result column="enabled2" property="enabled" />
        </collection>
    </resultMap>


 <!--通过用户id查询菜单列表-->
    <select id="getMenuByAdminId" resultMap="Menus">
        select
            DISTINCT
            m1.*,
            m2.id as id2,
            m2.url as url2,
            m2.path as path2,
            m2.component as component2,
            m2.name as name2,
            m2.keepAlive as keepAlive2,
            m2.requireAuth as requireAuth2,
            m2.parentId as parentId2,
            m2.enabled as enabled2
        from
            t_menu m1,
            t_menu m2,
            t_admin_role ar,
            t_menu_role mr
        where
            m1.id =  m2.parentId
          and m2.id = mr.mid
          and mr.rid = ar.rid
          and ar.adminId = #{id}
          and m2.enabled = true
        order by m1.id
    </select>

这里用关联查询,这几张表分别是 菜单表,角色菜单表,用户角色表,关联关系如下:

通过关联查出来的结果直接用Map中的 colection给放到实体类中的children属性里即可一次性查出来

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值