SSM实现树形菜单

SSM框架完成单表数据树形菜单实现

任务背景:

  • 最近在搭建基于SSM种子项目框架时,遇到了树形菜单加载问题。特此把解决的问题方案记录下去,供其他小伙伴参考和日后回顾。

方案分析

  • 方案选择
    • 一次性加载完,返回前台需要的数据结构
    • 点击加载,默认记载根层级的菜单。后续点击那一级菜单加载其下的子节点
    • 对节点进行查询,删除,修改,增加
  • 方案实现
    • 在这里只分析一次性加载实现
    • 对节点进行查询,删除,修改,增加

具体实现

- 表、数据资料

  • 数据库
    SSM实现树形菜单

  • 设置主键Id和parent_id的级联关 SSM实现树形菜单

直接撸起代码干起:

  • 实体类

      /**
       * 编号
       */
      private Long id;
    
      /**
       * 名称
       */
      private String name;
      /**
       * 父级Id
       */
      private Long parentId;
          /**
           * 子节点集合
           */
          List<Node> chilidren;
      
          public Node() {
          }
      
          public Node(Long id, String name, Long parentId, List<Node> chilidren) {
              this.id = id;
              this.name = name;
              this.parentId = parentId;
              this.chilidren = chilidren;
          }
      
          public Long getId() {
              return id;
          }
      
          public void setId(Long id) {
              this.id = id;
          }
      
          public String getName() {
              return name;
          }
      
          public void setName(String name) {
              this.name = name;
          }
      
          public Long getParentId() {
              return parentId;
          }
      
          public void setParentId(Long parentId) {
              this.parentId = parentId;
          }
      
          public List<Node> getChilidren() {
              return chilidren;
          }
      
          public void setChilidren(List<Node> chilidren) {
              this.chilidren = chilidren;
          }
    
  • Dao层和service层一样

      int insert(Node node);
       
      List<Node> getNodeTree();
      					
      List<Node> listChild(Long id);
      					
      Node selectById(Long id);
      					
      int updateById(Node node);
      					
      int deleteById(Long... id);
    
  • Impl实现层

      @Autowired
      private NodeDao nodeDao;
    
      @Override
      public int insert(Node node) {
          return nodeDao.insert(node);
      }
    
      @Override
      public List<Node> getNodeTree() {
          return nodeDao.getNodeTree();
      }
    
      @Override
      public List<Node> listChild(Long id) {
          return nodeDao.listChild(id);
      }
    
      @Override
      public Node selectById(Long id) {
          return nodeDao.selectById(id);
      }
    
      @Override
      public int updateById(Node node) {
          return nodeDao.updateById(node);
      }
    
      @Override
      public int deleteById(Long... id) {
          return deleteById(id);
      }
    
  • Controlle层

  •   @RestController
      @RequestMapping("/api/node")
      
      public class NodeController extends BaseApiController {
    
      @Autowired
      private NodeService nodeService;
    
    
      @GetMapping("/listChild")
      public Map<String,Object>listChild(@RequestParam Long id){
          return onDataResp(nodeService.listChild(id));
      }
    
      @GetMapping("/tree")
      public Map <String,Object> tree(){
          return onDataResp(nodeService.getNodeTree());
      }
    
      @GetMapping("/selectById")
      public Map <String,Object> selectById(@RequestParam Long id){
          return onDataResp(nodeService.selectById(id));
      }
    
    
    
      @GetMapping("/insert")
      public Map <String,Object> insert(@RequestParam Long parent_id,@RequestParam String name){
          Node node = new Node();
          node.setParentId(parent_id);
          node.setName(name);
          nodeService.insert(node);
          return onDataResp("添加成功");
      }
    
    
    
      @GetMapping("/update")
      public Map <String,Object> update(@RequestParam Long id,@RequestParam Long parent_id,@RequestParam String name){
          Node node = new Node();
          node.setId(id);
          node.setParentId(parent_id);
          node.setName(name);
          if (nodeService.updateById(node) >0) return onSuccessRep("修改成功");
          return onBadResp("修改失败");
      }
      
      @GetMapping("delete")
      public Map<String,Object>delete(@RequestParam Long id){
          nodeService.deleteById(id);
          return onBadResp("删除节点成功");
    
  • 重点的Mapper.xml文件

    <resultMap id="ParentTreeResultMap" type="com.my.blog.bean.Node">
      <result column="id" property="id"/>
      <result column="name" property="name"/>
      <result column="parent_id" property="parentId"/>
    
      <collection column="id" property="chilidren" select="listChild" ofType="com.my.blog.bean.Node" />
    </resultMap>
    
    <resultMap id="listChildResultMap" type="com.my.blog.bean.Node">
      <result column="id" property="id"/>
      <result column="name" property="name"/>
      <result column="parent_id" property="parentId"/>
      <collection column="id" property="chilidren"  select="listChild" ofType="com.my.blog.bean.Node" />
    </resultMap>
    
    <insert id="insert">
      INSERT INTO node(name,parent_id) VALUES (#{name},#{parentId})
    </insert>
    
    
      //子级节点查询(listChild)
    <select id="listChild" resultMap="listChildResultMap">
      SELECT id,name FROM node  WHERE parent_id = #{id}
    </select>
    
    
    <select id="selectById" resultMap="ParentTreeResultMap">
       SELECT id,name FROM node  WHERE id=#{id}
    </select>
      //父级节点查询
    <select id="getNodeTree" resultMap="ParentTreeResultMap">
      SELECT id,name FROM node  WHERE parent_id IS null
    </select>
    
    
    <update id="update">
    
      UPDATE node
      <set>
          <if test="name!=null"> name=#{name},</if>
          <if test="parentId !=null"> parent_id=#{parentId}</if>
      </set>
      WHERE id=#{id}
    
    </update>
    
    <delete id="delete">
     DELETE  FROM node WHERE id IN
         <foreach collection="array" index="index" item="item" open="(" separator="," close=")">
                    #{item}
    
         </foreach>
    
    </delete>
    

    Mybatis之高级映射collection (递归查出树形数据 )

    • 描述:利用Mybatis高级的映射关系,利用collection一对多关系,先查出父级节点方法: getNodeTree()(我的数据库父级节点设计为null)
    • 再去找字节级节点方法: listChild()递归查出树形菜单

结果的实现和展示:

  • 展示图片
    SSM实现树形菜单

  • Json数据

    		{
    "code": 200,
    "data": [
        {
            "id": 1,
            "name": "一级节点A",
            "chilidren": [
                {
                    "id": 4,
                    "name": "二级节点AA",
                    "chilidren": [
                        {
                            "id": 7,
                            "name": "三级节点AAA",
                            "chilidren": [
                                
                            ]
                        },
                        {
                            "id": 8,
                            "name": "三级节点aaa",
                        "chilidren": [
                            
                        ]
                    }
                ]
            },
            {
                "id": 5,
                "name": "二级节点aa",
                "chilidren": [
                    
                ]
            }
        ]
    },
    {
        "id": 2,
        "name": "一级节点a",
        "chilidren": [
            {
                "id": 6,
                "name": "二级节点BB",
                "chilidren": [
                    {
                        "id": 9,
                        "name": "三级节点BBB",
                        "chilidren": [
                            
                        ]
                    }
                ]
            }
        ]
    },
    {
        "id": 3,
        "name": "一级节点B",
        "chilidren": [
            
        ]
    }
    

    ]
    }

总结:

利用Mybatis的collection标签进行一对多递归查询树形数据结构,先查出父级节点再查询子级节点。数据库设置联级关系,达到父级节点和子级可以同时一起删除,完成树形查单的增删查改。(第一次写博客,希望大家能够支持和指出问题所有)