当前位置: 首页 > article >正文

05-学成在线课程分类查询

课程分类查询

界面原型

在新增课程基本信息界面中课程等级、课程类型、课程分类三处信息需要用户选择

在这里插入图片描述

当我们点击新增课程时,前端会请求内容管理服务中的content/course-category/tree-nodes接口获取课程分类表中的课程分类信息

在这里插入图片描述

响应数据模型

课程分类表course_category是一个树型结构表,通过parantid字段将表中的所有记录组成一个树

`

在内容管理服务的model工程中定义一个CourseCategoryTreeDto类存储课程分类信息中的数据

package com.xuecheng.content.model.dto;
/**
 * @description 课程分类树型结点dto
 * @author Mr.M
 * @date 2022/9/7 15:16
 * @version 1.0
 */
@Data
public class CourseCategoryTreeDto extends CourseCategory implements Serializable {
  // 存储当前节点(根节点的下属节点)的所有子节点
  List<CourseCategoryTreeDto> childrenTreeNodes;
} 

此接口要返回全部课程的分类信息并组成一个树型结构(JSON数组)返回给前端,数组的每个元素是课程分类根节点的子节点,每个子节点又有其对应的字节点

[
    // 根节点的子节点
    {
        // 1-2节点的基本信息
        "id" : "1-2",
        "isLeaf" : null,
        "isShow" : null,
        "label" : "移动开发",
        "name" : "移动开发",
        "orderby" : 2,
        "parentid" : "1",
         // 1-2节点的所有子节点信息
        "childrenTreeNodes" : [
         {
                // 1-2-1节点的子节点信息
                "childrenTreeNodes" : null,
                // 1-2-1节点的基本信息
                "id" : "1-2-1",
                "isLeaf" : null,
                "isShow" : null,
                "label" : "微信开发",
                "name" : "微信开发",
                "orderby" : 1,
                "parentid" : "1-2"
            },
            //1-2节点的其他子节点........
        ]
    },
    {
        // 1-1节点的基本信息
        "id" : "1-1",
        "isLeaf" : null,
        "isShow" : null,
        "label" : "前端开发",
        "name" : "前端开发",
        "orderby" : 1,
        "parentid" : "1" 
         // 1-1节点的子节点
        "childrenTreeNodes" : [
         {
                "childrenTreeNodes" : null,
                "id" : "1-1-1",
                "isLeaf" : null,
                "isShow" : null,
                "label" : "HTML/CSS",
                "name" : "HTML/CSS",
                "orderby" : 1,
                "parentid" : "1-1"
            },  
            //1-1节点的其他子节点........
    	]
    },
	//根节点的其他子节点........
]

接口定义(api工程)

从数据库中查询出根节点下所有的课程分类信息,然后在Java程序中遍历查询到的数据组成一个树形结构对象并返回

package com.xuecheng.content.api;
/**
 * <p>
 * 数据字典 前端控制器
 * </p>
 *
 * @author itcast
 */
@Slf4j
@RestController
@Api(value = "课程分类相关接口", tags = "课程分类相关接口")
public class CourseCategoryController {
    @Resource
    private CourseCategoryService courseCategoryService;
    
    @ApiOperation("课程分类相关接口")
    @GetMapping("/course-category/tree-nodes")
    public List<CourseCategoryTreeDto> queryTreeNodes() {
        return courseCategoryService.queryTreeNodes("1");
    }
}

业务开发(service层)

第一步: 使用表的自连接查询,连接条件为two.parentid = one.id(二级分类的父节点为一级分类),同时one.parentid = 1(一级分类的父节点为根节点)

  • 如果我们有三级分类的话,那么还得继续修改SQL语句
SELECT * FROM 
	course_category one
JOIN 
	course_category two 
ON 
	two.parentid = one.id
WHERE 
	one.parentid = '1'

select
       one.id            one_id,
       one.name          one_name,
       one.parentid      one_parentid,
       one.orderby       one_orderby,
       one.label         one_label,
       two.id            two_id,
       two.name          two_name,
       two.parentid      two_parentid,
       two.orderby       two_orderby,
       two.label         two_label
from 
   	   course_category one
inner join 
   	   course_category two 
on 
   	   one.id = two.parentid
where 
   	   one.parentid = 1 and one.is_show = 1 and two.is_show = 1
order by 
       one.orderby,two.orderby

如果当树的层级不固定时,使用with语法底层是利用MySQL的递归实现,把查询出来的结果再次代入到查询子句中继续查询

WITH RECURSIVE t1 AS (
    # 设置一个递归的初始值
    SELECT 1 AS n
    # UNION ALL 不断将每次递归得到的数据加入到表中
    UNION ALL
    # WHERE n < 5 则是终止条件
    SELECT n + 1 FROM t1 WHERE n < 5
)
SELECCT * FROM t1;
# t1 相当于一个表名
WITH RECURSIVE t1 AS (
    SELECT p.* FROM course_category p WHERE p.id = '1'
    UNION ALL
    SELECT c.* FROM course_category c JOIN t1 on c.parentid = t1.id
)

第二步:编写Mapper接口及其SQL映射文件

public interface CourseCategoryMapper extends BaseMapper<CourseCategory> {
    List<CourseCategoryTreeDto> selectTreeNodes();
}
<select id="selectTreeNodes" parameterType="string" resultMap="com.xuecheng.content.model.dto.CourseCategoryTreeDto">
    WITH RECURSIVE t1 AS (
        SELECT p.* FROM course_category p WHERE p.id = #{id}
        UNION ALL
        SELECT c.* FROM course_category c JOIN t1 WHERE c.parentid = t1.id
    )
    SELECT * FROM t1;
</select>

第三步: 编写Service接口及其实现类,使用Java代码将查询到的课程分类数据组装成树形结构

public interface CourseCategoryService {
    /**
     * 课程分类查询
     * @param id 根节点id
     * @return 根节点下面的所有子节点
     */
    List<CourseCategoryTreeDto> queryTreeNodes(String id);
}
@Slf4j
@Service
public class CourseCategoryServiceImpl implements CourseCategoryService {
    @Autowired
    private CourseCategoryMapper courseCategoryMapper;
    @Override
    public List<CourseCategoryTreeDto> queryTreeNodes(String id) {
        // 获取所有的子节点
        List<CourseCategoryTreeDto> categoryTreeDtos = courseCategoryMapper.selectTreeNodes(id);
        // 定义一个List,作为最终返回的数据
        List<CourseCategoryTreeDto> result = new ArrayList<>();
        // 为了方便找子节点的父节点,这里定义一个HashMap,key是节点的id,value是节点本身
        HashMap<String, CourseCategoryTreeDto> nodeMap = new HashMap<>();
        // 将数据封装到List中,只包括根节点的下属节点(1-1、1-2 ···),这里遍历所有节点
        categoryTreeDtos.stream().forEach(item -> {
            // 这里寻找父节点的直接下属节点(1-1、1-2 ···)
            if (item.getParentid().equals(id)) {
                nodeMap.put(item.getId(), item);
                result.add(item);
            }
            // 获取每个子节点的父节点,对于1-1的父节点1是不在Map集合当中的,所以不需要为父节点1设置ChildrenTreeNodes属性
            String parentid = item.getParentid();
            CourseCategoryTreeDto parentNode = nodeMap.get(parentid);
            // 判断HashMap中是否存在该父节点(按理说必定存在,以防万一)
            if (parentNode != null) {
                // 为父节点设置子节点(将1-1-1设为1-1的子节点)
                List childrenTreeNodes = parentNode.getChildrenTreeNodes();
                // 如果子节点暂时为null,则初始化一下父节点的子节点(给个空集合就行)
                if (childrenTreeNodes == null) {
                    parentNode.setChildrenTreeNodes(new ArrayList<CourseCategoryTreeDto>());
                }
                // 将子节点设置给父节点
                parentNode.getChildrenTreeNodes().add(item);
            }
        });
        // 返回根节点的直接下属节点(1-1、1-2 ···),下属节点已经设置了子节点属性
        return result;
    }
}

http://www.kler.cn/a/146994.html

相关文章:

  • Arduino(NodeMcu)上传程序时出现“上传错误:exit status 2”
  • 07 服务间调用:openFeign上下文信息丢失
  • 【无头双向链表和链表练习题2】
  • 【AI】MMLab环境搭建
  • linux下的工具---vim
  • 深度学习之图像分类(十四)CAT: Cross Attention in Vision Transformer详解
  • 测试数据随机,给2n个点,求所有偏移量,使得每两个点成为一个匹配
  • Wireshark的捕获过滤器
  • Unity之NetCode多人网络游戏联机对战教程(10)--玩家动画同步
  • LabVIEW当鼠标悬停在图形曲线上时显示坐标
  • 蓝桥杯每日一题2023.11.26
  • 一个C++ string使用问题的分析及解决
  • Junos webauth_operation.php 文件上传漏洞复现(CVE-2023-36844)
  • yolov5检测(前向)输入视频输出(不在图上画标签形式的原)图片的方法,及设置每隔几帧保存的方式(不每帧保存减少重复)
  • HCIA-RS基础-RIP路由协议
  • 如何将mobi、awz3、epub格式转化为pdf
  • 一体化污水处理设备各种材质的优缺点
  • 排序篇(六)----排序小结(不用三连,混流量券)
  • 五、双向NAT
  • SAP创建ODATA服务-Structure