首页 > 其他分享 >使用Mybatis生成树形菜单-适用于各种树形场景

使用Mybatis生成树形菜单-适用于各种树形场景

时间:2023-06-14 12:00:48浏览次数:38  
标签:菜单 MENU SYS 树形 NOW time Mybatis NULL

开发中我们难免会遇到各种树形结构展示的场景。比如用户登录系统后菜单的展示,某些大型购物网站商品的分类展示等等,反正开发中会遇到各种树形展示的功能,这些功能大概处理的思路都是一样的,所以本文就总结一下树形结构的代码生成,在开发的时候套用这种结构就可以了。

好了正文开始,首先相关的SQL脚本【MYSQL】提供给你(包吃包住包SQL)【如果巅峰留不住那就进厂包吃住】。

DDL语句:

CREATE TABLE `student`.`SYS_menu`(  
  `ID` INT(10) NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(200) NOT NULL,
  `permissions` VARCHAR(1000),
  `url` VARCHAR(200),
  `description` VARCHAR(2000),
  `icon_cls` VARCHAR(2000),
  `pid` INT(10),
  `status` INT(2),
  `resource_type` INT(2),
  `sort` INT(6),
  `create_time` TIMESTAMP,
  `update_time` TIMESTAMP,
  PRIMARY KEY (`ID`)
) ENGINE=INNODB CHARSET=utf8;

初始化语句:

INSERT INTO SYS_MENU(NAME,permissions,url,description,icon_cls,pid,STATUS,resource_type,create_time,update_time,SORT)

VALUES('主菜单',NULL,NULL,'数据主菜单',NULL,0,1,1,NOW(),NOW(),NULL) ;

INSERT INTO SYS_MENU(NAME,permissions,url,description,icon_cls,pid,STATUS,resource_type,create_time,update_time,SORT)

VALUES('菜单1',NULL,NULL,'菜单1',NULL,(SELECT * FROM (SELECT id FROM SYS_MENU WHERE NAME='主菜单') a ),1,1,NOW(),NOW(),1) ;

INSERT INTO SYS_MENU(NAME,permissions,url,description,icon_cls,pid,STATUS,resource_type,create_time,update_time,SORT)

VALUES('菜单2',NULL,NULL,'菜单2',NULL,(SELECT * FROM (SELECT id FROM SYS_MENU WHERE NAME='主菜单') a ),1,1,NOW(),NOW(),2) ;

INSERT INTO SYS_MENU(NAME,permissions,url,description,icon_cls,pid,STATUS,resource_type,create_time,update_time,SORT)

VALUES('菜单3',NULL,NULL,'菜单3',NULL,(SELECT * FROM (SELECT id FROM SYS_MENU WHERE NAME='主菜单') a ),1,1,NOW(),NOW(),3) ;

INSERT INTO SYS_MENU(NAME,permissions,url,description,icon_cls,pid,STATUS,resource_type,create_time,update_time,SORT)

VALUES('菜单1.1',NULL,NULL,'菜单1的子菜单',NULL,(SELECT * FROM (SELECT id FROM SYS_MENU WHERE NAME='菜单1') a ),1,1,NOW(),NOW(),1) ;

INSERT INTO SYS_MENU(NAME,permissions,url,description,icon_cls,pid,STATUS,resource_type,create_time,update_time,SORT)

VALUES('菜单1.2',NULL,NULL,'菜单1的子菜单',NULL,(SELECT * FROM (SELECT id FROM SYS_MENU WHERE NAME='菜单1') a ),1,1,NOW(),NOW(),2) ;

INSERT INTO SYS_MENU(NAME,permissions,url,description,icon_cls,pid,STATUS,resource_type,create_time,update_time,SORT)

VALUES('菜单1.3',NULL,NULL,'菜单1的子菜单',NULL,(SELECT * FROM (SELECT id FROM SYS_MENU WHERE NAME='菜单1') a ),1,1,NOW(),NOW(),3) ;

INSERT INTO SYS_MENU(NAME,permissions,url,description,icon_cls,pid,STATUS,resource_type,create_time,update_time,SORT)

VALUES('菜单2.1',NULL,NULL,'菜单2的子菜单',NULL,(SELECT * FROM (SELECT id FROM SYS_MENU WHERE NAME='菜单2') a ),1,1,NOW(),NOW(),1) ;

INSERT INTO SYS_MENU(NAME,permissions,url,description,icon_cls,pid,STATUS,resource_type,create_time,update_time,SORT)

VALUES('菜单2.2',NULL,NULL,'菜单2的子菜单',NULL,(SELECT * FROM (SELECT id FROM SYS_MENU WHERE NAME='菜单2') a ),1,1,NOW(),NOW(),2) ;

INSERT INTO SYS_MENU(NAME,permissions,url,description,icon_cls,pid,STATUS,resource_type,create_time,update_time,SORT)

VALUES('菜单2.3',NULL,NULL,'菜单2的子菜单',NULL,(SELECT * FROM (SELECT id FROM SYS_MENU WHERE NAME='菜单2') a ),1,1,NOW(),NOW(),3) ;

INSERT INTO SYS_MENU(NAME,permissions,url,description,icon_cls,pid,STATUS,resource_type,create_time,update_time,SORT)

VALUES('菜单3.1',NULL,NULL,'菜单3的子菜单',NULL,(SELECT * FROM (SELECT id FROM SYS_MENU WHERE NAME='菜单3') a ),1,1,NOW(),NOW(),1) ;

INSERT INTO SYS_MENU(NAME,permissions,url,description,icon_cls,pid,STATUS,resource_type,create_time,update_time,SORT)

VALUES('菜单3.2',NULL,NULL,'菜单3的子菜单',NULL,(SELECT * FROM (SELECT id FROM SYS_MENU WHERE NAME='菜单3') a ),1,1,NOW(),NOW(),2) ;

INSERT INTO SYS_MENU(NAME,permissions,url,description,icon_cls,pid,STATUS,resource_type,create_time,update_time,SORT)

VALUES('菜单3.3',NULL,NULL,'菜单3的子菜单',NULL,(SELECT * FROM (SELECT id FROM SYS_MENU WHERE NAME='菜单3') a ),1,1,NOW(),NOW(),3) 

数据结构一般就是上面得那样,只是初始化得数据按照你开发得需求初始化。

然后就是创建简单得项目,好了那我就贴出相关得代码,这些大家开发得时候可以根据需求进行嵌套使用。

// entity
@Data
@TableName("sys_menu")
public class SysMenu implements Serializable {
  private static final long serialVersionUID = 1L;
  @TableId
  private Integer id;
  private String name;
  private String permissions;
  private String url;
  private String description;
  private String iconCls;
  private Integer pid;
  private Integer status;
  private Integer resourceType;
  private Integer sort;
  private Date createTime;
  private Date updateTime;
  /**
   * 此处为了简单我就不新建DTO对象了,
   * 加一个children属性,注意如果不是数据库的字段一定要
   * 加下面d额那个注解
   */
  @TableField(exist=false)
  private List<SysMenu> children;

}
// mapper接口,很简单没有多余代码
public interface SysMenuDao extends BaseMapper<SysMenu> {
  
}
// mapper 文件也是没有多余的代码,使用Mybatis-Plus特有的就行
// 其中下面的resultMap也可以去掉。
<mapper namespace="io.renren.mapper.SysMenuDao">
  <!-- 可根据自己的需求,是否要使用 -->
    <resultMap type="io.renren.domain.SysMenu" id="sysMenuMap">
        <result property="id" column="ID"/>
        <result property="name" column="name"/>
        <result property="permissions" column="permissions"/>
        <result property="url" column="url"/>
        <result property="description" column="description"/>
        <result property="iconCls" column="icon_cls"/>
        <result property="pid" column="pid"/>
        <result property="status" column="status"/>
        <result property="resourceType" column="resource_type"/>
        <result property="sort" column="sort"/>
        <result property="createTime" column="create_time"/>
        <result property="updateTime" column="update_time"/>
    </resultMap>
</mapper>
// service 主要的逻辑代码就在这里。
public interface SysMenuService extends IService<SysMenu> {

    List<SysMenu> getMenuTree();
}

@Service("sysMenuService")
public class SysMenuServiceImpl extends ServiceImpl<SysMenuDao, SysMenu> implements SysMenuService {

    @Autowired
    private SysMenuDao sysMenuDao ;
    @Override
    public List<SysMenu> getMenuTree() {
        //查询出所有菜单
        List<SysMenu> sysMenus = sysMenuDao.selectList(null);
        //2、组装成树形结构
        //2.1)、找到所有的一级菜单
        List<SysMenu> level1Menus = sysMenus.stream().filter(sysMenu ->
                sysMenu.getPid() == 0
        ).map((menu) -> {
            menu.setChildren(getChildrens(menu, sysMenus));
            return menu;
            // 排序
        }).sorted((menu1, menu2) -> {
            return (menu1.getSort() == null ? 0 : menu1.getSort()) - (menu2.getSort() == null ? 0 : menu2.getSort());
        }).collect(Collectors.toList());
        return level1Menus;
    }
    
       //递归查找所有菜单的子菜单,主要就是用了这个递归查询。
       // 我也都写了相关的注释。
    private List<SysMenu> getChildrens(SysMenu root, List<SysMenu> all) {

        List<SysMenu> children = all.stream().filter(sysMenu -> {
            return sysMenu.getPid() == root.getId();
        }).map(sysMenu -> {
            //1、找到子菜单
            sysMenu.setChildren(getChildrens(sysMenu, all));
            return sysMenu;
        }).sorted((menu1, menu2) -> {
            //2、菜单的排序
            return (menu1.getSort() == null ? 0 : menu1.getSort()) - (menu2.getSort() == null ? 0 : menu2.getSort());
        }).collect(Collectors.toList());
        return children;
    }

有的小伙伴可能会说,博主我们项目使用的jdk7 。上面的代码使用不了啊,这篇文章对我来说不合适啊。好了安排上,既然写文章我就要写的明明白白,下面是不使用Stream流完成的功能。

List<SysMenu> getMenuTreeVerLowJava8() ;
 
   @Override
    public List<SysMenu> getMenuTreeVerLowJava8() {
        List<SysMenu> sysMenus = sysMenuDao.selectList(null);
        List<SysMenu> tree = new ArrayList<>();
        for (SysMenu sysmenu: sysMenus) {
            if (sysmenu.getPid()==0){
               tree.add(getChildrens02(sysmenu,sysMenus)) ;
            }
        }
        return tree;
    }
 
    /**
     * 不使用stream的递归调用
     * @param list
     * @return
     */
    private SysMenu getChildrens02(SysMenu sysMenu, List<SysMenu> list) {

        List<SysMenu> children = new ArrayList<SysMenu>();
        for (SysMenu sysMenu2 : list) {
            if (sysMenu2.getPid() == sysMenu.getId()) {
                // 递归调用
                SysMenu result = getChildrens02(sysMenu2, list);
                children.add(result);
            }
        }
        sysMenu.setChildren(children);
        return sysMenu;
    }

使用Java7的菜单树我没有进行排序,Java7的排序使用起来也很简单,相信大家开发的时候都使用过,大家可以自行完成排序。生成的树形结构太多我就不贴出来了肯定是正确的。

开发中就是需要这种记录,为什么呢,当你没看到这篇文章你写一个树形结构的代码可能需要一天,而你点一下关注,后面开发中你遇到这种功能的开发一个小时应该就能搞定并且还没有问题,极大的提高了开发效率,领导看到你效率那么高应该也会很高兴,说不定升职加薪就在眼前。点点关注何乐而不为呢?生活中也一样,你同样需要记录总结,这样你应该也越走越顺,比如你今天上班路上遇到一个坑,你记住了。下次走过这里你就会避开这个坑,路也越走越顺了。

标签:菜单,MENU,SYS,树形,NOW,time,Mybatis,NULL
From: https://www.cnblogs.com/scott1102/p/17479822.html

相关文章

  • MyBatisPlus_动态更新
    场景:项目整合了mybatisplus,进行update更新,前端传值为空时,数据库也进行了更新,导致原来的值丢失。解决方案:在实体类上使用@TableField注解/*联系人手机号码*/@TableField(updateStrategy=FieldStrategy.NOT_EMPTY)privateStringphone;这样,当前端传过来的phone参数为......
  • 基于SpringBoot+MyBatis+Thymeleaf的学生管理系统搭建
    学生管理系统Maven工程搭建【步骤】:打开IDEA工具,选择创建一个新工程。选择SpringInitializr,点击Next按钮。大家也可以通过Spring提供的在线创建的方式创建工程,访问(https://start.spring.io),然后将创建后的工程代码zip包解压后,使用IDEA导入工程。这种方式不在本文描述......
  • win11更改鼠标右键菜单栏
    **右键菜单改回Win10(展开)**1.新建记事本:(格式为.txt)2.填写脚本内容regadd"HKCU\Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}\InprocServer32"/f/vetaskkill/f/imexplorer.exe&startexplorer.exe3.保存文件,记事本后缀.txt改为.bat确定4.......
  • mybatis批量插入的四种方式
    一、循环插入publicvoidinsert(List<User>userList){userList.forEach(user->userDao.insert(user));}<insertid="insert">INSERTINTO`demo`.`user`(`username`,`address`,`remark`,`age`,`create_time`)VALUES(#{u......
  • andorid-动态选项菜单的实现
    andorid-动态选项菜单的实现 通过重载方法publicbooleanonPrepareOptionsMenu(Menumenu){}来实现。 @Override publicbooleanonCreateOptionsMenu(Menumenu){ returnsuper.onCreateOptionsMenu(menu); } @Override publicbooleanonPrepareOptionsMenu(Menume......
  • Spring boot2 数据访问之Druid数据源+Mybatis
    Mybatis官方地址 1、查找Mybatis相关starter 官方文档 这里注意查找指定版本的Starter 这里以2.2.2为例,查看官方的pom.xml如下:<?xmlversion="1.0"encoding="UTF-8"?><!--Copyright2015-2022theoriginalauthororauthors.Licensedunderthe......
  • 解决方案 | Adobe Acrobat XI Pro 右键菜单“在Acrobat中合并文件”丢失的最佳修复方
    1、问题 AdobeAcrobatXIPro右键菜单“转换为AdobePDF”与“在Acrobat中合并文件”不见了。 2、解决方案桌面左下角搜索“添加或删除程序”,按照如下修复即可。 ......
  • 微信公众号开发C#系列-8、自定义菜单及菜单响应事件的处理
    本文目录1、概述2、自定义菜单的规则3、自定义菜单接口可实现按钮类型的种类4、创建菜单4.1、创建菜单的接口4.2、使用Senparc.Weixin.MPSDK创建自定义菜单4.3、查询已创建的菜单4.4、删除已创建的菜单5、菜单响应事件的处理5.1、点击菜单拉取消息时的事件推送5.2、击菜单跳转链......
  • 把公司的ruoyi项目mybatis升级到mybatis-plus
    ruoyi项目mybatis升级到mybatis-plus1、ruoyi-common\pom.xml模块添加整合依赖2、ruoyi-admin文件application.yml,修改mybatis配置为mybatis-plus3、添加MybatisPlus配置MybatisPlusConfig.java4、升级后需要修改的地方4.1service接口修改4.2service实现修改4.3mapper修改1、......
  • spring boot连接Mybatis数据库的配置文件(MySql、SQLserver、Oracle)
    序号类型地址1MySQLMySQL操作之概念、SQL约束(一)2MySQLMySQL操作之数据定义语言(DDL)(二)3MySQLMySQL操作之数据操作语言(DML)(三)4MySQLMySQL操作之数据查询语言:(DQL)(四-1)(单表操作)5MySQLMySQL操作之数据查询语言:(DQL)(四-2)(多表查询)6MySQLMySQL操作之数据控制语言:(DC)(五)7MySQLMySQL操作之数......