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

这篇具有很好参考价值的文章主要介绍了使用Mybatis生成树形菜单-适用于各种树形场景。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

好了正文开始,首先相关的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的排序使用起来也很简单,相信大家开发的时候都使用过,大家可以自行完成排序。生成的树形结构太多我就不贴出来了肯定是正确的。

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

到了这里,关于使用Mybatis生成树形菜单-适用于各种树形场景的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 适用各种行情,使用网格交易策略实现自动高效套利

    网格交易是量化交易的一种,在指定的区间内,将资金分成N份,先用一部分资金初始建仓,每下跌一定比例买入1份,每上涨一定比例卖出1份,反复低吸高抛,赚取差价。 网格交易策略对于不能实时盯盘的交易者来说,是一个非常理想的自动交易工具!它的优点非常明显,无

    2024年02月04日
    浏览(44)
  • 使用hutool工具生成树形结构

    假设要构建一个菜单,可以实现智慧库房,菜单的样子如下: 那这种结构如何保存在数据库中呢?一般是这样的: ​ 每条数据根据 parentId 相互关联并表示层级关系, parentId 在这里也叫外键 id parentId name 1 0 智慧库房 2 1 RFID 3 1 智慧大屏 4 1 智能密集架 5 1 环境管控 使用步骤:

    2024年02月14日
    浏览(57)
  • 【SQL开发实战技巧】系列(三十):数仓报表场景☞树形(分层)查询如何排序?以及如何在树形查询中正确的使用where条件

    【SQL开发实战技巧】系列(一):关于SQL不得不说的那些事 【SQL开发实战技巧】系列(二):简单单表查询 【SQL开发实战技巧】系列(三):SQL排序的那些事 【SQL开发实战技巧】系列(四):从执行计划讨论UNION ALL与空字符串UNION与OR的使用注意事项 【SQL开发实战技巧】系列

    2023年04月09日
    浏览(70)
  • layui树形菜单的实现

    继续上一篇博客的内容,在原来代码的基础上实现树形菜单功能 在layui中,树形菜单是通过 Tree 组件实现的。Tree 组件提供了一种树形结构展示数据的方式,常用于显示层级结构的菜单、目录等。开发者可以通过配置项和方法对树形菜单进行定制和操作。 树形菜单是一种常见

    2024年02月15日
    浏览(48)
  • React18-树形菜单-递归

    https://github.com/dL-hx/manager-fe/commit/85faf3b1ae9a925513583feb02b9a1c87fb462f7 从接口获取城市数据,渲染出一个树形菜单 要求: 可以展开和收起 学会递归渲染出一个树形菜单, 并点击后可以展开和收起 通过对数据上添加控制字段(show)避免在子组件添加各种同步的useState,等字段.保证单向数据

    2024年01月22日
    浏览(71)
  • synchronized各种使用场景

    开启10个线程,每个线程中循环100次对result变量进行++自增,主线程等待10s后输出result值结果 结果 执行结果不一定是869,可能是其他的数,总之就是比正确的结果1000小 原因 result++这个操作的执行过程其实是3个步骤 读取result变量 将result变量进行+1 将result值再赋给result变量 详

    2023年04月23日
    浏览(44)
  • Layui之动态树 左侧树形菜单栏 详细全面

    ⭐ฅʕ•̫͡•ʔฅ本期看点:该篇是运用Layui框架来编写后台树形菜单栏,并且结合MySql来编写完成 目录 一.效果图 二.具体步骤  2.1 数据库   2.2 树形导航栏     第一个类:Treevo              第二个类:BuildTree: 2.3  Dao方法         2.3.1 basedao                

    2024年02月15日
    浏览(31)
  • MySQL分区表的正确使用方法,适用场景,建立分区的条件

    什么是MySQL分区? MySQL分区是将一张表分割成独立的子表的技术。每个子表被称为分区,它们有着相同的结构和字段,但存储着不同的数据。这项技术可以提高查询速度,减少日志文件和磁盘空间的使用。 建立分区的条件 要建立MySQL分区,需要满足以下几个条件: 1.所需的

    2024年02月07日
    浏览(46)
  • 探究Spring Bean的六种作用域:了解适用场景和使用方式

    主要对单例作用域与原型作用域进行重点说明,其余四个了解即可 单例作用域一般是默认的Bean作用域。Spring容器在第一次获取Bean时创建实例,并在后续请求中返回同一个实例。 例如: 我们现在创建一个公共的Bean供用户一与用户二使用,用户一再使用完后对其内容进行修改

    2024年02月15日
    浏览(36)
  • 【Axure动态面板】利用动态面板实现树形菜单的制作

    一 、先看效果         https://1poppu.axshare.com 二、实现思路 1 、菜单无非就是收缩和展开,动态面板有个非常好的属性: fit to content ,这个属性的含义是:面板的大小可以根据内容多少而变化; 2 、菜单的收缩和展开,可以通过切换面板的状态来实现即可,即每个菜单设置

    2024年02月14日
    浏览(55)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包