• 三级分类部分三级目录无法加载,后端接口能在前端返回所有数据


    项目场景:三类分类部分不显示

    实现ElementUI中三级分类的功能,发现没有前端三级目录的二级目录可以新建三级目录,数据库中也有数据,但是无法在前端显示!后端的接口没有返回数据库的数据。
    在这里插入图片描述


    问题描述:数据库序号128后的目录不显示

    提示:这里描述项目中遇到的问题:

    例如:数据传输过程中数据不时出现丢失的情况,偶尔会丢失一部分数据
    APP 中接收数据代码:

    @Override
    	public void run() {
    		bytes = mmInStream.read(buffer);
    		mHandler.obtainMessage(READ_DATA, bytes, -1, buffer).sendToTarget();
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5

    原因分析: 数据库&JAVA后端

    提示:例如:在骑行运动耳机目录之后新建的目录,前端界面显示新建成功,数据库也有数据,但是不会显示在前端。

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    数据库中新建数据成功,但是在骑行运动中不会显示出这个新建的婴儿车三级目录。
    在这里插入图片描述
    IDEA 日志打印记录显示插入成功
    在这里插入图片描述
    使用sql查询 parent_cid为128的二级目录
    在这里插入图片描述

    再使用接口测试前端界面没有婴儿车
    在这里插入图片描述

    代码:

    后端接口

    //controller层
      /**
         * 查出所有分类以及子分类,以树形结构组装起来
         */
        @RequestMapping("/list/tree")
        public R list(){
            List<CategoryEntity> entities = categoryService.listWithTree();
            return R.ok().put("data", entities);
        }
    
    //接口Service层
        List<CategoryEntity> listWithTree();
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    Service的具体实现

        @Override
        public List<CategoryEntity> listWithTree() {
            //1、查出所有分类
            List<CategoryEntity> entities = baseMapper.selectList(null);
    
            //2、 组装成父子的树形结构
                //2.1) 找到所有一级分类(父分类id为0)
            List<CategoryEntity> level1Menus = entities.stream().filter(categoryEntity ->
                    categoryEntity.getCatLevel() == 1
            ).map((menu)->{
    //            System.out.println(menu);
                menu.setChildren(getChildrens(menu,entities));
    //            menu.setChildren(getSubtreeById(menu.getCatId(), entities));
                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<CategoryEntity> getChildrens(CategoryEntity root,List<CategoryEntity> all){
    
            //1.找到当前菜单的子菜单(每个子菜单还有子菜单)
    //        Stream categoryEntityStream = all.stream().filter(entity -> (long)entity.getParentCid() == (long)root.getCatId()); //出bug语句
            Stream<CategoryEntity> categoryEntityStream = all.stream().filter(entity -> entity.getParentCid() == root.getCatId());
    
            Stream<CategoryEntity> mapEntityStream = categoryEntityStream.map(item -> {
                item.setChildren(getChildrens(item,all));
                return item;
            });
    
            List<CategoryEntity> children = mapEntityStream.sorted((menu1,menu2)->{
                return (menu1.getSort()==null?0:menu1.getSort()) - (menu2.getSort()==null?0:menu2.getSort());
            }).collect(Collectors.toList());
            return  children;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    解决方案:

    提示:CatID为128以后的二级目录都不显示数据库中有的三级目录

    1 数据库序号问题

    DROP TABLE IF EXISTS `pms_category`;
    
    CREATE TABLE `pms_category` (
      `cat_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '分类id',
      `name` char(50) DEFAULT NULL COMMENT '分类名称',
      `parent_cid` bigint(20) DEFAULT NULL COMMENT '父分类id',
      `cat_level` int(11) DEFAULT NULL COMMENT '层级',
      `show_status` tinyint(4) DEFAULT NULL COMMENT '是否显示[0-不显示,1显示]',
      `sort` int(11) DEFAULT NULL COMMENT '排序',
      `icon` char(255) DEFAULT NULL COMMENT '图标地址',
      `product_unit` char(50) DEFAULT NULL COMMENT '计量单位',
      `product_count` int(11) DEFAULT NULL COMMENT '商品数量',
      PRIMARY KEY (`cat_id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=1424 DEFAULT CHARSET=utf8mb4 COMMENT='商品三级分类';
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    AUTO_INCREMENT=1424 原来的数据库是1434,改成了1424让cat_id自增 序号不断层,问题还是解决。 开始以为是数据库很多序号乱码,后面才发现是128二级目录开始出问题。

    2 JAVA层面

    1 递归改成非递归写法

            //原版代码
    //        List children = all.stream().filter(categoryEntity -> {
    //            return categoryEntity.getParentCid() == root.getCatId();
    //        }).map(categoryEntity->{
    //            //2.利用映射递归查找 子菜单的子菜单
    //            categoryEntity.setChildren(getChildrens(categoryEntity,all));
    //            return categoryEntity;
    //        }).sorted((menu1,menu2)->{
    //            //3.对当前菜单进行排序,升序排序
    //            return (menu1.getSort()==null?0:menu1.getSort()) - (menu2.getSort()==null?0:menu2.getSort());
    //        }).collect(Collectors.toList());
    //
    //        return children;
    
            //非递归写法
    //        List result = new ArrayList<>();
    //        for (int i = 0; i < all.size(); i++){
    //            CategoryEntity entity = all.get(i);
    //            if (entity.getParentCid() == root.getCatId()) {
    //                result.add(entity);
    //            }
    //        }
    //        System.out.println(result);
    //
    //        for (int i = 0; i < result.size(); i++){
    //            CategoryEntity current = result.get(i);
    //            List sub = new ArrayList<>();
    //            for (int j = 0; j < all.size(); j++){
    //                CategoryEntity entity = all.get(j);
    //                if (entity.getParentCid() == current.getCatId()) {
    //                    List subsub = new ArrayList<>();
    //                    for (int k = 0; k < all.size(); k++){
    //                        CategoryEntity subEntity = all.get(k);
    //                        if (subEntity.getParentCid() == entity.getCatId()){
    //                            subsub.add(subEntity);
    //                        }
    //                    }
    //                    entity.setChildren(subsub);
    //                    sub.add(entity);
    //                }
    //            }
    //            current.setChildren(sub);
    //        }
    //
    //        return result;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    还是不行

    2重新写接口: 查询cat_id为128的子目录

    //Controller层
        /**
         * 信息
         */
        @RequestMapping("/info/{catId}")
        //@RequiresPermissions("product:category:info")
        public R info(@PathVariable("catId") Long catId) {
    
            CategoryEntity category = categoryService.getById(catId);
            return R.ok().put("data", category);
        }
    
    //Service层
        List<CategoryEntity> getSubtreeById(long catId);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    接口实现功能

        @Override
        public List<CategoryEntity> getSubtreeById(long catId) {
            List<CategoryEntity> entities = baseMapper.selectList(null);
    
            List<CategoryEntity> filterList = entities.stream().filter(item -> item.getParentCid() == catId)
                    .map(item -> {
                        item.setChildren(getSubtreeById(item.getCatId()));
                        return item;})
                    .collect(Collectors.toList());
            return filterList;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    前端端口测试: 直接通过id的方式能够查询到父ID为128的所有目录,既婴儿车的父目录找到了。
    在这里插入图片描述
    后续按照这个思路重新写程序能够实现三级分类展现所有子目录的功能,但是对bug产生的原因不太清晰!!!

    解决方法:加上(long)向下转型自动拆箱

    改变一行代码
    在这里插入图片描述
    就是因为递归调用了太多次,自动装箱成Long对象,但是Long对象装箱的源码实现跟128有很大的关系!! 下面解释中的Integer是一个道理,(Integer) 128 == (Integer) 128 为false,所以128之后的二级目录都不满足这个判断,所以他们的三级目录无法加载!!!
    具体代码实现可以看引用!!!

    Integer类 -128~127 之间的值都是直接从缓存中取出的,(Integer)127 == (Integer)127两边装箱后,实际指向堆内存中同一个对象,大于127 后就new一个新的对象返回。(Integer)128 == (Integer)128,装箱为引用类型后,没有做缓存,指向堆内存中不同对象,所以比较结果为false。至于为什么要缓存,若不缓存,每次都要new一个新对象,资源消耗多,所以缓存一些常用的数,来减少资源损耗。
    ————————————————
    版权声明:本文为CSDN博主「有时候我也会」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/weixin_43849277/article/details/108275997

    总结: 递归使用要慎重,自动装箱的隐藏机制需要熟悉

    开发过程中不要随便用递归!!!Debug不好调整,遇到其他问题结合,真的是头皮发麻!!!本文只是精简的讲述了核心找bug的过程,但是Debug打各种条件断点,查看Tomcat源码,StackFlow看英文,,,等等困扰了我一天的bug,终于跟冠哥合理解决了!!!

    推荐看一下阿里开发手册对递归使用的建议!!!

  • 相关阅读:
    【数据结构与算法】链表的实现以及相关算法
    计算机组成原理平时作业二
    学习Java的第十一天
    一键导入文件夹下全部文件,按文件名快速分类保存
    使用PyTorch Profiler进行模型性能分析,改善并加速PyTorch训练
    ORB-SLAM2算法15之回环检测线程Loop Closing
    Qt+ECharts开发笔记(四):ECharts的饼图介绍、基础使用和Qt封装百分比图Demo
    通师高专科技创新社训练赛(20221127)
    docker命令
    钉钉微应用 - - - - - 钉钉内打开新页签
  • 原文地址:https://blog.csdn.net/qq_41398619/article/details/133897704