The third-level directory of the third-level classification cannot be loaded. The back-end interface can return all data on the front-end.

Directory

  • Project scene: The three-category classification part is not displayed
  • Problem description: Directories after database serial number 128 are not displayed
  • Cause analysis: Database & JAVA backend
    • Code:
      • backend interface
  • solution:
    • 1 Database serial number problem
    • 2 JAVA level
      • 1 Change recursive to non-recursive writing
      • 2 Rewrite the interface: Query the subdirectory with cat_id 128
  • Solution: Add (long) downward transformation to automatically unbox
  • Summary: Use recursion with caution, and be familiar with the hidden mechanism of autoboxing.

Project scenario: The three categories are not displayed

Implement the third-level classification function in ElementUI. It is found that a second-level directory that does not have a front-end third-level directory can create a third-level directory. There is also data in the database, but it cannot be displayed on the front-end! The backend interface does not return database data.

Problem description: Directories after database serial number 128 are not displayed

Tips: Describe the problems encountered in the project here:

For example: data may be lost from time to time during data transmission, and occasionally part of the data may be lost.
Code for receiving data in APP:

@Override
public void run() {<!-- -->
bytes = mmInStream.read(buffer);
mHandler.obtainMessage(READ_DATA, bytes, -1, buffer).sendToTarget();
}

Cause analysis: Database & JAVA backend

Tip: For example: for a directory created after the Cycling Sports headphone directory, the front-end interface shows that the creation is successful, and the database also has data, but it will not be displayed on the front-end.




The newly created data in the database is successful, but the newly created third-level stroller catalog will not be displayed during cycling.

The IDEA log print record shows that the insertion was successful.

Use sql to query the secondary directory whose parent_cid is 128

Then use the interface to test the front-end interface without a stroller.

Code:

Backend interface

//controller layer
  /**
     * Find all categories and subcategories and assemble them in a tree structure
     */
    @RequestMapping("/list/tree")
    public R list(){<!-- -->
        List<CategoryEntity> entities = categoryService.listWithTree();
        return R.ok().put("data", entities);
    }

//Interface Service layer
    List<CategoryEntity> listWithTree();


Specific implementation of Service

 @Override
    public List<CategoryEntity> listWithTree() {<!-- -->
        //1. Find all categories
        List<CategoryEntity> entities = baseMapper.selectList(null);

        //2. Assemble into a parent-child tree structure
            //2.1) Find all first-level categories (parent category id is 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;
    }

    //Recursively search the submenus of all menus
    private List<CategoryEntity> getChildrens(CategoryEntity root,List<CategoryEntity> all){<!-- -->

        //1. Find the submenus of the current menu (each submenu also has submenus)
// Stream<CategoryEntity> categoryEntityStream = all.stream().filter(entity -> (long)entity.getParentCid() == (long)root.getCatId()); // Bug statement
        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;

Solution:

Tip: Second-level directories with CatIDs after 128 will not display the third-level directories in the database.

1 Database serial number problem

DROP TABLE IF EXISTS `pms_category`;

CREATE TABLE `pms_category` (
  `cat_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'category id',
  `name` char(50) DEFAULT NULL COMMENT 'Category name',
  `parent_cid` bigint(20) DEFAULT NULL COMMENT 'parent category id',
  `cat_level` int(11) DEFAULT NULL COMMENT 'level',
  `show_status` tinyint(4) DEFAULT NULL COMMENT 'Whether to display [0-not displayed, 1 displayed]',
  `sort` int(11) DEFAULT NULL COMMENT 'sort',
  `icon` char(255) DEFAULT NULL COMMENT 'icon address',
  `product_unit` char(50) DEFAULT NULL COMMENT 'unit of measurement',
  `product_count` int(11) DEFAULT NULL COMMENT 'product quantity',
  PRIMARY KEY (`cat_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1424 DEFAULT CHARSET=utf8mb4 COMMENT='Three-level product classification';

AUTO_INCREMENT=1424 The original database was 1434, but it was changed to 1424 to allow cat_id to increase automatically. The serial number continued to increase, and the problem was still solved. At first I thought it was because there were many garbled serial numbers in the database, but later I discovered that there was a problem with the 128 secondary directory.

2 JAVA level

1 Change recursive writing to non-recursive writing

 //Original code
// List<CategoryEntity> children = all.stream().filter(categoryEntity -> {<!-- -->
// return categoryEntity.getParentCid() == root.getCatId();
// }).map(categoryEntity->{<!-- -->
// //2. Use mapping to recursively search for submenus of submenus.
// categoryEntity.setChildren(getChildrens(categoryEntity,all));
// return categoryEntity;
// }).sorted((menu1,menu2)->{<!-- -->
// //3. Sort the current menu in ascending order
// return (menu1.getSort()==null?0:menu1.getSort()) - (menu2.getSort()==null?0:menu2.getSort());
// }).collect(Collectors.toList());
//
// return children;

        //Non-recursive writing
// List<CategoryEntity> 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<CategoryEntity> sub = new ArrayList<>();
// for (int j = 0; j < all.size(); j + + ){<!-- -->
// CategoryEntity entity = all.get(j);
// if (entity.getParentCid() == current.getCatId()) {<!-- -->
// List<CategoryEntity> 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;

Or not

2 Rewrite the interface: Query the subdirectory with cat_id 128

//Controller layer
    /**
     * information
     */
    @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 layer
    List<CategoryEntity> getSubtreeById(long catId);

Interface implementation function

 @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;
    }

Front-end port test: All directories with a parent ID of 128 can be queried directly through the id, that is, the parent directory of the stroller has been found.

Later, rewriting the program according to this idea can realize the function of displaying all subdirectories in three-level classification, but the cause of the bug is not clear! ! !

Solution: Add (long) downward transformation to automatically unboxing

change a line of code

It is because it is called recursively too many times and is automatically boxed into a Long object. However, the source code implementation of Long object boxing has a lot to do with 128! ! Integer in the explanation below is the same. (Integer) 128 == (Integer) 128 is false, so the second-level directories after 128 do not satisfy this judgment, so their third-level directories cannot be loaded! ! !
For specific code implementation, please see the reference! ! !

Integer class – The values between -128~127 are all taken directly from the cache. (Integer)127 == (Integer)127 After boxing on both sides, it actually points to the same object in the heap memory. If it is greater than 127, a new one will be created. The object is returned. (Integer)128 == (Integer)128. After boxing as a reference type, there is no caching and it points to different objects in the heap memory, so the comparison result is false. As for why it is necessary to cache, if it is not cached, a new object will be created every time, which consumes a lot of resources, so some commonly used numbers are cached to reduce resource consumption.
—————-
Copyright statement: This article is an original article by CSDN blogger “Sometimes I Can”, and it follows the CC 4.0 BY-SA copyright agreement. Please attach the original source link and this statement when reprinting.
Original link: https://blog.csdn.net/weixin_43849277/article/details/108275997

Summary: Use recursion with caution, and be familiar with the hidden mechanism of autoboxing

Don’t use recursion casually during development! ! ! Debug is difficult to adjust, and when combined with other problems, it really makes your scalp numb! ! ! This article only briefly describes the process of finding core bugs, but Debug sets various conditional breakpoints, checks Tomcat source code, StackFlow looks at English, etc. The bugs that have been bothering me for a day were finally solved reasonably by Brother Guan! ! !

It is recommended to read the Alibaba Development Manual’s suggestions on the use of recursion! ! !