最终效果

image.png

数据库表设计:

image.png
image.png

实现懒加载

首页分类展示需求:
1、第一次刷新主页查询大分类,渲染展示到首页
2、如果鼠标移动到了大分类上面,则加载器子分类的内容,如果分类已存在,则不加载(懒加载)

1、获取一级分类

一级分类在页面开始生命周期时即请求后端获取

  1. ====================== Controller ======================
  2. @ApiOperation(value = "获取商品分类(一级分类)", notes = "获取商品分类(一级分类)", httpMethod = "GET")
  3. @GetMapping("/cats")
  4. public MyJSONResult cats() {
  5. List<Category> list = categoryService.queryAllRootLevelCat();
  6. return MyJSONResult.ok(list);
  7. }
  8. ====================== Service ======================
  9. @Transactional(propagation = Propagation.SUPPORTS)
  10. @Override
  11. public List<Category> queryAllRootLevelCat() {
  12. Example example = new Example(Category.class);
  13. Example.Criteria criteria = example.createCriteria();
  14. criteria.andEqualTo("type",1);
  15. List<Category> result = categoryMapper.selectByExample(example);
  16. return result;
  17. }

2、根据一级分类id获取其子分类

1)、编写sql语言

  1. SELECT
  2. f.`id` AS id,
  3. f.`name` AS `name`,
  4. f.type AS type,
  5. f.father_id AS fatherId,
  6. c.id AS subId,
  7. c.`name` AS subName,
  8. c.type AS subType,
  9. c.father_id AS subFatherId
  10. FROM
  11. category f
  12. LEFT JOIN #🔥自联表查询🔥
  13. category c
  14. ON
  15. f.id = c.father_id
  16. WHERE
  17. f.father_id = 1

image.png

2)、分析创建二级VO、三级VO

我们可以看到通过联表查询,二级分类都是重复的,所以我们可以将二级分类整合成为一个VO,这个二级分类里又含有它的三级分类VO List。
最终返回给前端数据如下:

  1. "data": [
  2. {
  3. "id": 11, // ==================== 二级分类 ====================
  4. "name": "蛋糕",
  5. "type": "2",
  6. "fatherId": 1,
  7. "subCatList": [ // 👇👇👇👇👇👇👇👇二级分类下的三级分类👇👇👇👇👇👇👇👇
  8. {
  9. "subId": 37,
  10. "subName": "蒸蛋糕",
  11. "subType": "3",
  12. "subFatherId": 11
  13. },
  14. {
  15. "subId": 38,
  16. "subName": "软面包",
  17. "subType": "3",
  18. "subFatherId": 11
  19. }
  20. //...
  21. ] // 👆👆👆👆👆👆👆二级分类下的三级分类👆👆👆👆👆👆👆
  22. },
  23. {
  24. "id": 12,
  25. "name": "点心",
  26. "type": "2",
  27. "fatherId": 1,
  28. "subCatList": [
  29. {
  30. "subId": 44,
  31. "subName": "肉松饼",
  32. "subType": "3",
  33. "subFatherId": 12
  34. },
  35. {
  36. "subId": 45,
  37. "subName": "华夫饼",
  38. "subType": "3",
  39. "subFatherId": 12
  40. }
  41. //...
  42. ]
  43. }
  44. ]

所以我们创建俩个VO来封装返回给前端你的数据,由前端进行解析

  1. package com.shiers.pojo.vo;
  2. import java.util.List;
  3. /**
  4. * 二级分类VO
  5. *
  6. * @author shierS
  7. * @date 2021/5/29
  8. */
  9. public class CategoryVO {
  10. private Integer id;
  11. private String name;
  12. private String type;
  13. private Integer fatherId;
  14. //三级分类VO list
  15. private List<SubCategoryVO> subCatList;
  16. //省略get、set方法
  17. }
  1. package com.shiers.pojo.vo;
  2. /**
  3. * 三级分类VO
  4. *
  5. * @author shierS
  6. * @date 2021/5/29
  7. */
  8. public class SubCategoryVO {
  9. private Integer subId;
  10. private String subName;
  11. private String subType;
  12. private Integer subFatherId;
  13. //省略get、set方法
  14. }

3)、创建自定义mapper

由于我们使用了通用mapper,它只能用于单表查询,对于自联表(多表查询)需要我们自定义mapper
创建CategoryMapperCustom,custom代表是我们自定义的mapper
返回类型封装在List

  1. public interface CategoryMapperCustom {
  2. public List<CategoryVO> getSubCatList(Integer rootCatId);
  3. }

创建CategoryMapperCustom.xml

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
  3. <mapper namespace="com.shiers.mapper.CategoryMapperCustom">
  4. <resultMap id="myCategoryVO" type="com.shiers.pojo.vo.CategoryVO">
  5. <id column="id" property="id"/>
  6. <result column="name" property="name"/>
  7. <result column="type" property="type"/>
  8. <result column="fatherId" property="fatherId"/>
  9. <!--
  10. collection 标签:用于定义关联的lsit集合类型的封装规则
  11. property:对应三级分类的list属性名
  12. ofType:集合的类型,三级分类vo
  13. -->
  14. <collection property="subCatList" ofType="com.shiers.pojo.vo.SubCategoryVO">
  15. <id column="subId" property="subId"/>
  16. <result column="subName" property="subName"/>
  17. <result column="subType" property="subType"/>
  18. <result column="subFatherId" property="subFatherId"/>
  19. </collection>
  20. </resultMap>
  21. <select id="getSubCatList" resultMap="myCategoryVO" parameterType="int">
  22. SELECT
  23. f.`id` AS id,
  24. f.`name` AS `name`,
  25. f.type AS type,
  26. f.father_id AS fatherId,
  27. c.id AS subId,
  28. c.`name` AS subName,
  29. c.type AS subType,
  30. c.father_id AS subFatherId
  31. FROM
  32. category f
  33. LEFT JOIN
  34. category c
  35. ON
  36. f.id = c.father_id
  37. WHERE
  38. f.father_id = #{rootCatId}
  39. </select>
  40. </mapper>

4)、Service

  1. @Autowired
  2. private CategoryMapperCustom categoryMapperCustom; //🔥使用我们自定义mapper🔥
  3. @Transactional(propagation = Propagation.SUPPORTS)
  4. @Override
  5. public List<CategoryVO> getSubCatList(Integer rootCatId) {
  6. List<CategoryVO> subCatList = categoryMapperCustom.getSubCatList(rootCatId);
  7. return subCatList;
  8. }

5)、Controller

  1. @ApiOperation(value = "获取商品子分类", notes = "获取商品子分类", httpMethod = "GET")
  2. @GetMapping("/subCat/{rootCatId}")
  3. public MyJSONResult subCat(
  4. @ApiParam(name = "rootCatId", value = "一级分类id", required = true)
  5. @PathVariable Integer rootCatId) {
  6. if (rootCatId == null) {
  7. return MyJSONResult.errorMsg("分类不存在");
  8. }
  9. List<CategoryVO> list = categoryService.getSubCatList(rootCatId);
  10. return MyJSONResult.ok(list);
  11. }