在线学习平台------手把手教程👈
用户管理
添加功能增强
新增属性
若依里的用户模块(SysUser)是没有课程这一属性的,要实现我们自己的课程分页查询功能
这个位置传入的实体类SysUser要加上classId,记得加上get、set方法
更改sql语句
ctrl + 鼠标左键不断点进去,查看调用位置
加入swagger文档:
package com.ruoyi.web.controller.system.SysUserController加上Api(tags = "用户管理")
在add方法上加ApiOperation("用户添加")
user_name是账号,nick_name才是昵称
所需参数
修改功能增强
和添加操作一样,需要在sql语句那边加上classId属性
查询功能
修改之前要写上先写查询功能
也和添加操作一样,一直点到sql语句的位置
课程模块:
班级名称和教师名称是采用关联的方式得到
前期准备:
先在domain自动生成实体类MsCourse
用lombok代替get、set方法,数据类型都改成包装类
设置实体类的自动递增、主键、自动填充
package com.mashang.elearing.domain;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.util.Date;
@Data
public class MsCourse {
@TableId(type = IdType.AUTO)
private Long courseId;
private String courseName;
private String courseCover;
private Long classId;
private Long teacherId;
private String delFlag;
@TableField(fill = FieldFill.INSERT)
private String createBy;
@TableField(fill = FieldFill.INSERT)
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private String updateBy;
@TableField(fill = FieldFill.INSERT_UPDATE)
//设置返回格式
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
private String remark;
}
分页查询课程
先在package com.mashang.elearing.domain.vo;生成对应的Vo
package com.mashang.elearing.domain.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ApiModel("查询课程分页")
@Data
public class MsCoursePageVo {
@ApiModelProperty("课程id")
private Long courseId;
@ApiModelProperty("课程名称")
private String courseName;
@ApiModelProperty("课程封面")
private String courseCover;
@ApiModelProperty("班级id")
private Long classId;
@ApiModelProperty("班级名称")
private String className;
@ApiModelProperty("教师名称")
private String teacherName;
@ApiModelProperty("教师id")
private Long teacherId;
@ApiModelProperty("备注")
private String remark;
}
因为是关联查询,不能用MyBatis-Plus,只能老实用MyBatis
package com.mashang.elearing.mapper;在这个位置建一个接口MsCourseMapper
在resources下面建一个文件夹(directory)mapper,在mapper下建一个xml-MsCourseMapper,这一个xml里面要绑定上面的MsCourseMapper
第一步:
在package com.mashang.elearing.mapper里继承BaseMapper<MsCourse>,再写一个方法
//分页需要传入page对象和条件构造器对象,两个参数要用@Param区别,
// 导入的都是mybatis-plus里的对象
//@Param是导自于ibatis里的
Page<MsCoursePageVo> page(@Param("page")Page<MsCoursePageVo> page,
@Param(Constants.WRAPPER)Wrapper wrapper);
第二步:
去对应的xml实现这个方法
第三步
在service层建一个 IMsCourseService 继承 IService<MsCourse>
在serivce层下的impl包下建一个MsCourseServiceImpl 继承(extends) ServiceImpl<MsCouseMapper,MsCourse> 再 实现自己的 IMsCourseService接口
第四步
在IMsCourseSerive写上对应的方法
//Pager里面放了 pageNum,和pageSize,支持通过教师id和名称来搜索
//教师id是用下拉框来实现的
//班级名称是用模糊查询来实现的
Page<MsCoursePageVo> page(Pager pager,Long teacherId,String courseName);
第五步
去MsCourseServiceImpl去实现这个方法
记得要注入Mapper层的对象
@Autowired
private MsCourseMapper msCourseMapper;
@Override
public Page<MsCoursePageVo> page(Pager pager, Long teacherId, String courseName) {
//拿到page对象
Page<MsCoursePageVo> p = new Page<>(pager.getPageNum(),pager.getPageSize());
//拿到构造器对象,这里只能用普通的QueryWrapper
//关联查询不能使用lamdaQueryWrapper
QueryWrapper<MsCoursePageVo> qw = new QueryWrapper<>();
qw.ne("t1.del_flag",2);
qw.eq(teacherId != null,"t1.teacher_id",teacherId);
qw.like(StringUtils.isNotEmpty(courseName),"t1.course_name",courseName);
qw.orderByDesc("t1.create_time");
//page方法需要一个page对象和条件构造器对象
return msCourseMapper.page(p,qw);
}
按降序排列,把新增二点放在最前面
第六步:
创建控制层MsCourseController,控制层上记得写上@Api和@ApiOperation
固定写法@RestController和@RequestMapping("/course")记得写上
然后注入的是IMsCourseService
//这里注入的是Service层的那个接口
@Autowired
private IMSCourseService msCourseService;
@ApiOperation("分页查询")
@GetMapping("/list")
//TableData是用来返回分页数据的
//@Validated参数验证,分页页码和条数必填
public TableData<MsCoursePageVo> page(@Validated Pager pager, Long teacherId, String courseName){
//msCourseService.page返回的是一个分页的Page对象
Page<MsCoursePageVo> page = msCourseService.page(pager, teacherId, courseName);
//注意这里返回的是集合
List<MsCoursePageVo> records = page.getRecords();
long total = page.getTotal();
return TableData.success(records,total);
}
添加接口
课程需要courseCover、courseName、classId、teacherId(下拉框)
设置要添加的的参数实体类
在params包下创建添加的实体类
com.mashang.elearing.domain.params.course;
package com.mashang.elearing.domain.params.course;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
@ApiModel("课程添加参数")
@Data
public class MsCourseCreate {
//课程Id可以在设置自动递增,courseId不用填
@ApiModelProperty(value = "课程名称",required = true) //这里的required只是建议
@NotBlank(message = "课程名称不能为空") //这里的NotBlank是必须的
private String courseName;
//NotBlank一般用于字符串
//NotNull一般用于 Long
@ApiModelProperty(value = "课程封面",required = true)
@NotBlank(message = "封面不能为空")
private String courseCover;
@ApiModelProperty(value = "班级id",required = true)
@NotNull(message = "班级id不能为空")
private Long classId;
@ApiModelProperty(value = "教师id",required = true)
@NotNull(message = "教师id不能为null")
private Long teacherId;
@ApiModelProperty("备注")
private String remark;
}
添加调用的是save方法,传入的是MsCourse,需要将MsCourseCreate转成MsCourse
传参转化
在com.mashang.elearing.mapping包下建一个接口MsCourseMapping
MsCourseMapping INSTANCE = Mappers.getMapper(MsCourseMapping.class);
List<MsClassPageVo> to(List<MsClass> msClasses);
代码
@ApiOperation("课程添加")
@PostMapping
public Result create(@RequestBody @Validated MsCourseCreate courseCreate){
MsCourse msCourse = MsCourseMapping.INSTANCE.to(courseCreate);
return Result.to(msCourseService.save(msCourse));
}
修改接口
修改相较于添加,要多传入一个课程Id,courseId为主键
设置要修改的参数实体类
赋值添加接口的传参,在com.mashang.elearing.domain.params.course这个这个位置创建一个
MsCourseUpdate实体类,加上课程Id,其他和添加接口一致
传参转化
MsCourse to(MsCourseUpdate update);
代码
@ApiOperation("课程修改")
@PutMapping
//Json的形式传、并且需要参数验证
public Result update(@RequestBody @Validated MsCourseUpdate update){
MsCourse msCourse = MsCourseMapping.INSTANCE.to(update);
return Result.to(msCourseService.updateById(msCourse));
}
删除接口
删除采用的是假山,调用的是UpdateById
@ApiOperation("课程删除")
@DeleteMapping("/{courseId}")
// @PathVariable参数放在路径上
public Result delete(@PathVariable Long courseId){
MsCourse msCourse = new MsCourse();
msCourse.setCourseId(courseId);
msCourse.setDelFlag("2");
return Result.to(msCourseService.updateById(msCourse));
}
查询详情接口
创建Vo
在com.mashang.elearing.domain.vo创建对应的Vo
package com.mashang.elearing.domain.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ApiModel("查询课程详情")
@Data
public class MsCourseDtlVo {
//这里不能只返回班级id和教师id,对应的名称也要用关联查询查出来
@ApiModelProperty("课程id")
private Long courseId;
@ApiModelProperty("课程名称")
private String courseName;
@ApiModelProperty("课程封面")
private String courseCover;
@ApiModelProperty("班级id")
private Long classId;
@ApiModelProperty("班级名称")
private String className;
@ApiModelProperty("教师名称")
private String teacherName;
@ApiModelProperty("教师id")
private Long teacherId;
@ApiModelProperty("备注")
private String remark;
}
写sql语句
教师名称和班级名称要用关联查询把他们查出来
之前在courseMapper的xml写过一样的查询语句,可以将之前的语句抽取出来公用
mapper层
在MsCourseMapper里加上方法
写上对应的sql语句,查询课程详情和查询课程列表的返回值一样,但最好要单独分开
返回的时候不需要转,sql语句的resultmap已经是我们需要的内容了
xml实现
<resultMap id="getDtlByIdMap" type="msCourseDtlVo">
<id property="courseId" column="course_id"></id>
<result property="courseName" column="course_name"></result>
<result property="courseCover" column="course_cover"></result>
<result property="classId" column="class_id"></result>
<result property="teacherId" column="teacher_id"></result>
<result property="className" column="class_name"></result>
<result property="teacherName" column="nick_name"></result>
<result property="remark" column="remark"></result>
</resultMap>
<select id="getDtlById" resultMap="getDtlByIdMap">
<include refid="listVo"></include>
where t1.course_id = #{courseId}
</select>
<sql id ="listVo">
SELECT
t1.course_id,
t1.course_name,
t1.course_cover,
t1.class_id,
t1.teacher_id,
t2.class_name,
t3.nick_name,
t1.remark
FROM
ms_course AS t1
LEFT JOIN ms_class AS t2 ON t1.class_id = t2.class_id
-- AND t2.class_id = t1.course_id
LEFT JOIN sys_user AS t3 ON t3.user_id = t1.teacher_id
</sql>
service层
同时在IMsCourseService加上对应的方法,然后实现它
最终代码代码
@ApiOperation("查询详情")
@GetMapping("/{courseId}")
// @PathVariable参数放在路径上
public Result<MsCourseDtlVo> getById(@PathVariable Long courseId){
//这个位置不需要转,直接返回就行
return Result.success(msCourseService.getDtlById(courseId));
}
查询教师列表
sql1
得到每个教师对应的信息
where后面这样写健壮性低,(如果删除了一个教师,又填了一个,role_id就变成了4)可以用一个专门的标识teacher来过滤
sql2
t1和t2关联得到每个用户的身份id,再用这个身份id去关联角色表,找出对应标识为teacher的数据
如果删除了一个教师,再新增,那么新的role_id虽然为4,但角色的唯一标识依然是teacher
这两张表可以得到role_id
再用这个role_id,就可以得到role_key
上面的sql语句只需要user_id和nick_name就可以了
根据唯一标识(role_key获取对应用户信息)
实体类
在对应位置com.ruoyi.system.domain.vo创建实体类
(这个功能是系统模块的)
在mapper层写上对应方法去实现
<resultMap id="selectUsersByRoleKeyMap" type="roleUserVo">
<id property="userId" column="user_id"></id>
<result property="nickName" column="nick_name"></result>
</resultMap>
<select id="selectUsersByRoleKey" resultMap="selectUsersByRoleKeyMap">
SELECT
t1.user_id,
t1.nick_name
from sys_user t1
left join sys_user_role t2
on t1.user_id = t2.user_id
LEFT JOIN sys_role t3
on t3.role_id = t2.role_id
WHERE t3.role_key = #{RoleKey}
And t1.del_flag != '2'
</select>
service层
controller
控制层的调用在ruoyi-admin的SysUserController里
@ApiOperation(value = "根据roleKey获取用户",notes = "teacher代表教师")
@GetMapping("/users/{roleKey}")
public AjaxResult getUsersByRoleKey(@PathVariable String roleKey){
return success(userService.selectUsersByRoleKey(roleKey));
}