learning-online-content-api工程的com.swx.content.api包下创建控制类

api.CourseCategoryController
/**
* <p>
* 课程分类信息 前端控制器
* </p>
*
* @author sw-code
* @since 2023-08-18
*/
@Api(value = "课程分类信息管理接口")
@RestController
@RequestMapping("/course-category")
public class CourseCategoryController {

}

查询所有类别

课程类别是树形表结构,在查询到时候用到了MySQL8的递归查询,在代码中处理查询结果将二级类别添加到父类别的childrenTreeNodes列表中。

接口信息如下

路径地址 http://localhost:63040/content/course-category/tree-nodes
请求方式 GET
请求参数
返回结果 List

返回结果VO

CourseCategoryTreeVO
@Data
@EqualsAndHashCode(callSuper = true)
public class CourseCategoryTreeVO extends CourseCategory implements Serializable {

private static final long serialVersionUID = 1L;

List<CourseCategoryTreeVO> childrenTreeNodes;
}

定义Mapper

找到CourseCategoryMapper,定义递归查询方法

/**
* <p>
* 课程分类 Mapper 接口
* </p>
*
* @author sw-code
* @since 2023-08-18
*/
public interface CourseCategoryMapper extends BaseMapper<CourseCategory> {

public List<CourseCategory> selectTreeNodes(@Param("id") String id);

}

resources/mapper/CourseCategoryMapper.xml中实现该方法:

CourseCategoryMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.swx.content.mapper.CourseCategoryMapper">

<select id="selectTreeNodes" parameterType="string" resultType="com.swx.content.model.po.CourseCategory">
WITH RECURSIVE t1 as (
SELECT c1.* FROM course_category c1 WHERE id = #{id}
UNION ALL
SELECT c2.* FROM course_category c2 INNER JOIN t1 ON t1.id = c2.parentid
)
SELECT * FROM t1
order by t1.id
</select>
</mapper>

树型表的标记字段是什么?如何查询MySQL树型表

树型表的标记字段是parentid即父节点id;查询方法一般有两种:
1)当层级固定时可以用表的自连接进行查询
2)如果灵活查询每个层级可以使用mysql递归方法,使用WITH RECURSIVE t1 AS() 实现

resultType和resultMap的区别

resultType需要实体类和查询的字段名对应,会自动映射
resultMap为自定义映射规则,当查询字段名和实体类不匹配(别名)时可通过resultMap实现一对一映射;此外resultMap还可以进行一对多映射(集合)。

#{}和${}有什么区别?

#{}是标记一个占位符,可防治sql注入
${} 用于动态sql中拼接字符串,可能导致sql注入

定义Service

Service就是将递归查询的结果进行组装,形成二级树形结构。

如果参数id是’1’,则代表查询所有类别,此时和不使用递归查询没区别
但是当id是’1-1’这种二级目录时,查询的是以当前二级目录为根目录的递归结果。

找到CourseCategoryService接口,定义课程查询接口

CourseCategoryService
/**
* <p>
* 课程分类 服务类
* </p>
*
* @author sw-code
* @since 2023-08-18
*/
public interface CourseCategoryService extends IService<CourseCategory> {

/**
* 查询课程分类信息
*
* @return 树形结构的分类信息
*/
List<CourseCategoryTreeVO> treeNodes(String id);
}

实现该方法,找到其实现类CourseCategoryServiceImpl

CourseCategoryServiceImpl
/**
* <p>
* 课程分类 服务实现类
* </p>
*
* @author sw-code
* @since 2023-08-18
*/
@Service
public class CourseCategoryServiceImpl extends ServiceImpl<CourseCategoryMapper, CourseCategory> implements CourseCategoryService {

/**
* 查询课程分类信息
*
* @return 树形结构的分类信息
*/
@Override
public List<CourseCategoryTreeVO> treeNodes(String id) {
// 查询数据
List<CourseCategory> courseCategories = baseMapper.selectTreeNodes(id);
// 将数据转换为VO形式
List<CourseCategoryTreeVO> courseCategoryVos = courseCategories.stream().map(item -> {
CourseCategoryTreeVO vo = new CourseCategoryTreeVO();
BeanUtils.copyProperties(item, vo);
return vo;
}).collect(Collectors.toList());

// 转为Map<id, vo>的形式
Map<String, CourseCategoryTreeVO> map = courseCategoryVos.stream()
.filter(item -> !id.equals(item.getId()))
.collect(Collectors.toMap(CourseCategory::getId, value -> value, (key1, key2) -> key1));

// 组装树形结构
ArrayList<CourseCategoryTreeVO> results = new ArrayList<>();
courseCategoryVos.stream()
.filter(item -> !id.equals(item.getId()))
.forEach(item -> {
if (item.getParentid().equals(id)) {
// 根节点
results.add(item);
}
// item的父节点
CourseCategoryTreeVO categoryTreeVO = map.get(item.getParentid());
if (categoryTreeVO != null) {
if (categoryTreeVO.getChildrenTreeNodes() == null) {
categoryTreeVO.setChildrenTreeNodes(new ArrayList<>());
}
// 添加到其父节点
categoryTreeVO.getChildrenTreeNodes().add(item);
}
});
return results;
}
}

定义Controller

CourseBaseInfoController
/**
* <p>
* 课程分类信息 前端控制器
* </p>
*
* @author sw-code
* @since 2023-08-18
*/
@Api(value = "课程分类信息管理接口")
@RestController
@ResponseResult
@RequestMapping("/course-category")
public class CourseCategoryController {

private final CourseCategoryService courseCategoryService;

public CourseCategoryController(CourseCategoryService courseCategoryService) {
this.courseCategoryService = courseCategoryService;
}

@ApiOperation("课程查询接口")
@GetMapping("/tree-nodes")
public List<CourseCategoryTreeVO> treeNodes() {
return courseCategoryService.treeNodes("1");
}

}

Push到Git

commit "完成课程类别查询功能"