开发者学堂课程【微服务+全栈在线教育实战项目演练(SpringCloud Alibaba+SpringBoot):课程管理-课程信息确认】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/667/detail/11389
课程管理-课程信息确认
内容介绍
一、最终发布
二、前端部分
一、最终发布
1.含义
完成了第二步创建课程大纲,进行第三步最终发布。当在第二步点击下一步时,会来到第三步。
之前都已经将课程信息给添加完毕,第三步是为了对之前添加的课程信息做个确认。查看是之前添加的内容是否有问题,有问题可以返回修改,没有问题则选择发布课程。
也就是如下图将课程信息做一个最终显示,如显示课程封面、课程名称、课程价格和课程分类和讲师等等,将数据在页面中做个显示。
2. 分析
要实现第三步最终发布,首先查看页面中的网址:http://localhost:9528/#/course/publish/1234747900958183425中数字部分1234747900958183425就是我们的课程 id,而有了课程 id 后课程名称、课程价格和课程分类数据的值,此外还有课程简介和课程内所属讲师都可以被查出来。
第一步操作,首先要做的是写个课程接口,根据课程 id ,将其中数据的值查出来。查看数据可以知道,根据课程id查其中的课程封面,价格和名称。这三个数据在课程表 edu_course 中能够查到,但其他数据课程分类在此表中无法查到,课程分类需要查分类表,课程简介需要查简介表,课程讲师则需要查讲师表。
所以此时课程的数据无法通过一张表查出来,需要查四张表,针对此情况,第一种方式:可以使用之前章节小节的封装方式,但此时采用此方法并不合适。在实际中一般思路:当查询的表过多,同时查询的操作过于复杂,常使用手写 sql 语句的方式做实现,而不用其他方法。
3. 介绍三种连接
所以此时我们写一个 sql 语句将其做到,根据课程 id 将其中的课程封面、课程名称、课程价格、分类、简介和讲师数据通过 sql 语句查出来。
这些数据查询多张表才可以得到,一般编写sql语句实现
多表连接查询
#内连接
#左外链接
#右外连接
因为要做一个课程信息分类,如图数据要查询多张表才可以得到,所以不采用封装等方式,采用编写 sql 语句来实现。
所以先编写 sql 语句之后再整合到项目中去。此时为多张表,所以此时要做多表连接查询,Mysql 多表连接查询有以下几种方式比较常见:1.内连接 2.左外连接 3.右外连接。根据实际,我们分析三种方式哪种较为合适。
比方此时在方框中有诸多数据,左表为分类表,右表为课程表,假设在左边的分类表有三个分类,id分别为1,2和3。同时对应着1为前端,2为后端,3为运维;
而在右边的课程表中,以便区分id为11,12和13表示课程id,对应着其中三个课程11为 java,12为 vue,13为 mysql。最后一行存放的为分类表中的 id 值值,表示为两张表的关系。
如:java 属于后端2,vue 属于前端1,mysql 不属于前端,后端和运维中的任何一个,为 null 表示空。在此我们使用这张图说明各连接表达的含义。
① 第一种方式:内连接
表示查询两张表有关联的数据叫内连接。假设做内连接操作,在此有关联数据则为方框内的前两行数据,因为 java 与后端有关联,vue 与前端有关联,而运维和mysql 在其中并没有关联。所以内连接在查找时,能查出前两行数据查不出来 mysql 和运维这两条数据,因为两者没有关联,内连接只能查询有关联的数据。
② 第二种方式:左外连接
表示让左边的分类表连接右边的课程表,即左边表所有数据都查出来,右边表就查询关联的。
左边表有前端,后端和运维,都查出来即便运维并没有关联。而右边表 java 和 vue都有关联,mysql 并没有关联,所以 mysql 不查出来。此时查出来的为左表的所有数据加上右表的 java 和 vue。
③ 第三种方式:右外查询
与左外查询相反,右外查询是查右表所有数据,左表查相关的数据。就是右表11,12和13全部查出来,但是左表的前端和后端有,运维没有,因为运维没有关联。
以上就是三种查询方式:内连接,左外连接和右外连接。同学们要自行背记清楚。同时这三种查询方式,在实际操作中使用最多的是内连接和左外连接,因为左外和右外连接是一样的性质,所以使用右外也是没有错的。
4.确定连接方式-左外连接
在课程信息确认中使用内连接是可行的,但在此有一个特点:课程中可能没有简介,课程简介为 null,或者是没有分类和讲师,都可能为空,所以使用内连接并不合适。所以在此使用左外连接,达到的效果为:课程不管有没有简介,分类和讲师都全部查出来,但是简介,分类和讲师只查询关联数据。所以使用左外连接最合适,将课程全部查出来,其他部分只查询相关部分。
接下来在 MySQL 中按照分析编写左外连接的 sql 语句
注意:在关联分类表中,它有一级分类 id 和二级分类 id 两个 id 。但一级二级存的都是 edu_subject 这张表的 id。在此如果一张表中多个字段同时关联同一张表,可以查询多次,如先用一级分类关联表然后查出来,再用二级分类关联表查出来,第一次查一级分类,第二次查二级分类通过两次将数据都查出来。
l 根据课程 id 查询课程信息使用左外连接的 sql 语句实现如下:
#内连接
#左外链接
#右外连接
#SELECT*表示查全部,将其改为查找具体的值
#ec.id 表示课程 id,ec.price 表示课程价格,lesson_num 是课程数,ec.title 表示课程名称
SELECT ec.id, ec.title,ec.price,ec.lesson_num,
#ecd.description为描述
ecd.description,
#et.name是讲师姓名
et.name,
#一级分类,因为课程名称也为 title,为方便区分重命名为 onesubject
es1.title As oneSubject,
#二级分类,重命名为 twoSubject
es2.title As twoSubject
#将edu_course ec,进行左外连接关联 edu_course_description 课程简介表,LEFT表示左外连接,其中 OUTER 可写可不写
#JOIN 表示关联,ON 后为两张表的关联条件-根据 id 关联。
FROM edu_course ec LEFT OUTER JOIN edu_course_description ecd ON ec.id=ecd.id
#关联讲师表,关联条件为讲师 id
LEET OUTER JOIN edu_teacher et oN ec.teacher_id=et.id
#关联分类表的一级分类,es1 是查出来的一级分类。
LEET OUTER JOIN edu_subject es1 ON ec.subject_parent_id=es1.id
#关联分类表的二级分类,es2 是查出来的二级分类,到此就完成了两次分类的查找,es1 为一级分类,es2 为二级分类。
LEFT OUTER JOIN edu_subject es2 ON ec.subject_id=es2.id
#最后条件,根据课程 id1234747900958183425来查询里面的数据。
WHERE ec.id=’1234747900958183425’
到此根据课程 id 查其中课程的信息的 sql 语句就到此完成了,其中关联了多张表,写了左外连接做了关联。
将课程id输入在WHAT条件中,显示报错:’es2.title as twoSubject’,即为在es2.title as twoSuject 最后少加了逗号。解决错误后,将其执行。可以看到数据成功显示出来,这就是根据课程id显示它的信息。在图中可以知道第一列id为课程id,第二列 title 为课程名称,第三列price为课程价格,第四列 lesson_num 为课时数,第五列 description 为描述,第六列name为讲师名称,第七列 oneSubject为一级分类,第八列 twoSubjct 为二级分类。
二、后端部分
1.分析
完成前端,我们来到后端。查看结构,在之前所写结构中,我们只写到 Service 部分,而在 mapper 中并没有做很多操作。
但在 mapper 结构中,里面既有接口同时又有配置文件。
而在接口中可以定义方法,而在配置文件中可以编写 sql 语句,所以此时就要用到我们的配置文件,在里面写 sql 语句。在此首先把 Mapper 写完,再进行调用,因为重点是写 mapper。
2.新建一个 CoursePublishVo 类
首先在 EduCourseMapper 中先定义一个根据课程 id 定义查询课程基本信息的方法。因为查询会返回一个对象,而之前定义并不合适,所以我们将其提前定义一个待会专门做封装。在 vo 中新建一个 class。
将其命名为 CoursePublishVo。
之后再其中定义我们需要的对象属性,在课件中将其复制在CoursePublishVo.java中。
l 对象属性如下:
private String title;private String cover;
private Integer lessonNum;
private String subjectLevelOne;
private String subjectLevelTwo;private String teacherName;
private String price;//只用于显示
l CoursePublishVo.java 代码
import lombok. Data;
//添加注解,生成get,set方法
@Data
public class CoursePublishVo{
//添加课程id值
private String id;
private String title;//课程名称
private String cover;//课程封面
private Integer lessonNum;//课时数
private String subjectLevelOne;//一级分类
private String subjectLevelTwo;//二级分类
private String teacherName;//讲师名称
private String price;//价格
//只用于显示
}
3.编写EduCourseMapper.java代码
完成上述代码后,在 mapper 接口中定义 getPublishCourseInfo(String courseId)方法,同时传入参数 courseId 。
l EduCourseMapper.java 代码:
package com. atguigu. eduservice. mapper ;
import com. atguigu.eduservice.entity.EduCourse:
//对象和包的全路径
import rom. atguigu.eduservice.entity.vo.CoursePublishVo
import com. baomidou. mybatisplus.core.mapper.BaseMapper;
/**
*
*课程Mapper接口
*
*
* @author test java
*@since 2020-03-02
*/
public interface EduCourseMapper extends BaseMapper{
//定义getPublishCourseInfo方法,同时传入参数courseId
public CoursePublishVo getPublishCourseInfo(String courseId);
}
4.在 xml 配置中编写 sql 语句
定义完成后,找到这个 Mapper 对应的 xml 文件,在文件中编写 sql 语句:根据课程id查询课程确认信息,因为在此的查询语句较为复杂,所以自行编写 sql 语句。
l EduCourseMapper.xml代码如下:
#在其中有select标签,在标签中id为mapper接口中的方法名称,即getPublishCourseInfo。parameterType 为参数类型,为 String,可省略不写。resultType 为返回类型,在接口中返回的是一个对象,就将对象的包和类的全路径:com atguigu. eduservice.entity. vo.CoursePublishVo 给加上即可。
#同时注意 resultType 不要写错,除此之外还有 resultMap 表示可以自定义一个类型,在此我们使用的是 CoursePublishVo.java 中定义的类型。所以不能使用,要使用 resultMap 需要在 select 标签外再添加一个定义结果。
SELECT ec.id, ec.title, ec.price, ec.lesson_num,ecd.description,et.name,5.根据 CoursePublishVo 中的属性更改 sql 语句在 EduCourseMapper.xml 中编写完对应的 sql 语句后根据 CoursePublishVo.java中的属性更改数据库中的 sql 语句完成一一对应,添加封面属性 ec.cover,同时将原来课时数重命名为 lessonNum。同时去掉其中的描述 ecd.descriptionl 数据库中的 sql 语句(红色为变化部分):#内连接#左外链接#右外连接#SELECT*表示查全部,将其改为查找具体的值#添加封面属性 ec.cover,同时将原来课时数重命名为 lessonNumSELECT ec.id, ec.title,ec.price,ec.lesson_num AS lessonNum,ec.cover,#并未查找描述,去除 ecd.description,#ecd.description,#讲师名重命名为 teacherNameet.name AS teacherName,#一级分类重命名为 subjectLevelOnees1.title As subjectLevelOne,#二级分类重命名为 subjectLevelTwoes2.title As subjectLevelTwo#将查询条件 id 值变为,mapper 方法中传入的 courseId 参数#同时注意如果为一个参数时,可写任意名称,但不能为中文WHERE ec.id=#{courseId} 6.在 MySQL 中确认 sql 语句完全正确在 MySQL 中更改完成之后,点击查询,显示内容如图正确。7.将 sql 语句复制到 xml 配置中再将其复制到 EduCourseMapper.xml 中,方便查看错误。8. 最后更改查询条件 id① 改为 courseId复制之后,更改最后的查询条件id值为 getPublishCourseInfo 方法中传入的参数值courseId,因为此时的 id 值为固定的1234747900958183425,而我们需要的是每回调用 getPublishCourseInfo 方法传入的参数 courseId 值。要实现此操作,有两种方法。第一种:加个#和大括号,最后放入参数名称,常用此方法。如:WHERE ec.id=#{courseId}第二种:加上$符号和大括号,最后放入参数名称。但一般不适用$符号,因为它代表字符串拼接,会产生 sql 注入问题,所以使用第一种方法。如:WHERE ec.id=${courseId}② 注意最后注意其中的参数名称写法,当 mapper 中只有一个参数,在查询条件中写任意名称都可以,但不可以写中文。通常为了方便,都写和参数一样的名称,所以在此写 courseId。如 WHERE ec.id=${suibian}