mybatis 单表自关联 实现树结构的几种方式

javaBean如下:

public class Permission implements Serializable {
    private Integer id;
    private String name;
    private String icon;
    private String url;
    private boolean open;//树叶是否打开
    private Integer pid;//父id
    private boolean checked;//是否被选中
    private List<Permission> children =new ArrayList<Permission>();//子集合
}

第一种:使用mybatis映射实现:
1.在mapper映射文件中配置:

 <!--递归结果集合-->
<resultMap id="RecursionResultMap" type="com.ssm.bean.Permission">
  <id column="id" jdbcType="INTEGER" property="id" />
  <result column="pid" jdbcType="INTEGER" property="pid" />
  <result column="name" jdbcType="VARCHAR" property="name" />
  <result column="icon" jdbcType="VARCHAR" property="icon" />
  <result column="url" jdbcType="VARCHAR" property="url" />
  <!--一对多,递归配置-->
  <collection property="children" ofType="com.ssm.bean.Permission" column="id" select="recursionChildren"/>
</resultMap>
<select id="selectRoot" resultMap="RecursionResultMap">
  select id, pid, name, icon, url
  from t_permission where pid is null or pid =0
</select>
<select id="recursionChildren" resultMap="RecursionResultMap">
  select id, pid, name, icon, url
  from t_permission where pid = #{id}
</select>

2.Service层:调用selectRoot方法

public List<Permission> selectRoot() {
    return permissionMapper.selectRoot();
}

3.Controller层:

@RequestMapping("/permissionALL")
@ResponseBody
public List<Permission> all(){
    List<Permission> list= permissionService.selectRoot();
    return list;
}   

结果得到的:在这里插入图片描述

第二种:通过递归实现:
1.mapper.xml配置:

<resultMap id="BaseResultMap" type="com.ssm.bean.Permission">
  <id column="id" jdbcType="INTEGER" property="id" />
  <result column="pid" jdbcType="INTEGER" property="pid" />
  <result column="name" jdbcType="VARCHAR" property="name" />
  <result column="icon" jdbcType="VARCHAR" property="icon" />
  <result column="url" jdbcType="VARCHAR" property="url" />
</resultMap>
<select id="selectChildren" resultMap="BaseResultMap">
  select id, pid, name, icon, url
  from t_permission where pid = #{id}
</select>

2.Service层:

public List<Permission> selectChildren(Integer id) {
   	return permissionMapper.selectChildren(id);
 }

3.Controller层:

@RequestMapping("/initPermission1")
@ResponseBody
public Permission initPermission1(){
    Permission permission=new Permission ();
    try{
        permission.setId(1);//这个地方应该通过数据库查询出根节点,因为根节点id在数据库是1,所以偷了一下懒
        queryChildPermissions(permission);//递归得到全部节点
    }catch (Exception e){
        throw  e;
    }
    return permission;
}
private void queryChildPermissions (Permission permission){
    List<Permission> children=  permissionService.selectChildren(permission.getId());//通过id查询子集合
    permission.setChildren(children);//将查询出来的子节点集合放入到permission集合中
    for(Permission innerChildren:children){        //遍历出子集合的子集合
        queryChildPermissions(innerChildren);      //放入到子节点的子集合中
    }
}
4.调用initPermission1方法,查询结果和第一种方式是一致的,这两种方式不建议使用,因为每一次执行递归都会发sql语句,对资源占有很大。

第三种:一次查出全部记录,通过嵌套循环遍历结果
1.mapper.xml配置;

<resultMap id="BaseResultMap" type="com.ssm.bean.Permission">
  <id column="id" jdbcType="INTEGER" property="id" />
  <result column="pid" jdbcType="INTEGER" property="pid" />
  <result column="name" jdbcType="VARCHAR" property="name" />
  <result column="icon" jdbcType="VARCHAR" property="icon" />
  <result column="url" jdbcType="VARCHAR" property="url" />
</resultMap>
 <select id="selectAll" resultMap="BaseResultMap">
      select id, pid, name, icon, url
      from t_permission
 </select>

2.Service层:

public List<Permission> selectAll() {
    return permissionMapper.selectAll();
}

3.Controller层:

@RequestMapping("/initPermission2")
@ResponseBody
public Permission initPermission2(){

    Permission permission=new Permission ();
    List<Permission> lists=permissionService.selectAll();//查询所有节点
    try{
        for(Permission ps:lists){//遍历节点
            Permission child=ps;
            if(ps.getPid().equals(0)||ps.getPid()==null){//获取根节点,Integer类型是包装类,判断对象引用
                permission=ps;//根节点
            }else{
                for (Permission innerpermission:lists){
                    if(child.getPid()==innerpermission.getId()){//如果节点的的pid和集合中某个节点的id一致
                        Permission parent=innerpermission;//将这个节点命名为父节点
                        parent.getChildren().add(child);//然后把child放入到它的父亲集合中
                        break;
                    }
                }
            }
        }
    }catch (Exception e){
        throw  e;
    }
            return permission;
}
查询的结果和前面两种的结果一致,一次查出所有数据,通过嵌套循环遍历得到结果,不需要频繁发送sql语句,但是如果数据多的话,循环的次数过多,会影响性能

第四种:一次查出所有数据,通过Map集合实现树结构

Service层和mapper.xml 同第三种方式
Controller层:

@RequestMapping("/initPermission")
@ResponseBody
public Permission initPermission(){
    Permission permission=new Permission ();
    List<Permission> lists=permissionService.selectAll();//查询所有节点
    Map<Integer,Permission> map=new HashMap<Integer,Permission>();//将所有节点存入到map集合
    try{
        for(Permission ps:lists) {
           map.put(ps.getId(),ps);//将所有id做为key,Permission对象做值,存入到map集合
        }
        for(Permission ps:lists){//遍历所有节点
            Permission child=ps;
            if (child.getPid().equals(0)||child.getPid()==null){
                permission=ps;//取出根节点
            }else{
                Permission parent=map.get(child.getPid());//通过子节点的pid获取父节点
                parent.getChildren().add(child);//将子节点放入父节点中
            }
        }
    }catch (Exception e){
        throw  e;
    }
    return permission;
}
4种查询出来的结果都是一样的,相对而言通过Map实现树结构,效率是最高的
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值