目录
如果结果集合中有新的字段,接受的实体类中没有,不用新增字段,直接用别的字段,给结果集的属性起别名代替即可。
mp语法
service下的save方法
一行一列可以用getmap来获取(一行多列也可以?,)
查询指定列,适合用new Wrapper 来构建条件
只查询一个用one(结果集中只有一个用one)
LearningRecord oldRecord = lambdaQuery()
.eq(LearningRecord::getLessonId, recordDTO.getLessonId())
.eq(LearningRecord::getSectionId, recordDTO.getSectionId()).one();
更新,set可以有选择的进行更新
boolean update = lambdaUpdate()
.set(LearningRecord::getMoment, recordDTO.getMoment())
.set(finished, LearningRecord::getFinished, true)
.set(finished, LearningRecord::getFinishTime, recordDTO.getCommitTime())
.eq(LearningRecord::getId, oldRecord.getId())
.update();
select 只查询指定字段
.in .page方法(page参数接收的是一个new page)
循环依赖
springboot 2.6 以后不允许循环依赖,如果必须要用可以注入下一层,比如注入mapper层
参数校验
@validate
提交视频学习记录业务分析
视频播放每隔几秒 或者规定时间自动上传一次播放记录
学习中有很多个小节,这些小节中包括考试和播放视频,考完试就算完成一次小节,播放视频 播放到一定进度也视为完成当前小节。
如果是考试 直接新增学习记录(可能存在bug,如果多次考试)(并更新课表,已学完小节数目加一),
如果是视频,首先判断是否是第一次观看(查看学习记录里面有没有数据,没有则新增),如果有数据说明看过,更新观看到第几秒,判断是否是第一次学完,播放进度是否达到要求,旧的学习状态是否是没学完,更新课表(更新最近学习状态)
代码实现
service 里面 save 方法
private boolean handleVideoRecord(Long userId, LearningRecordFormDTO recordDTO) {
// search old record
// LearningRecord oldRecord = lambdaQuery()
// .eq(LearningRecord::getLessonId, recordDTO.getLessonId())
// .eq(LearningRecord::getSectionId, recordDTO.getSectionId()).one();
LearningRecord oldRecord = queryOldRecord(recordDTO.getLessonId(), recordDTO.getSectionId());
if (oldRecord == null){
// 不存在则新增
LearningRecord record = BeanUtils.copyBean(recordDTO, LearningRecord.class);
record.setUserId(userId);
boolean success = save(record);
if (!success){
throw new DbException("新增学习记录失败!");
}
return false;
}
// 存在 则更新
// 判断是否第一次完成
boolean finished = !oldRecord.getFinished() && recordDTO.getMoment() * 2 >= recordDTO.getDuration();
if (!finished){
LearningRecord record = new LearningRecord();
record.setLessonId(recordDTO.getLessonId());
record.setSectionId(recordDTO.getSectionId());
record.setMoment(recordDTO.getMoment());
record.setFinished(oldRecord.getFinished());
record.setId(oldRecord.getId());
// 添加到延迟队列
taskHandler.addLearningRecordTask(record);
return false;
}
// 更新数据
boolean update = lambdaUpdate()
.set(LearningRecord::getMoment, recordDTO.getMoment())
.set(finished, LearningRecord::getFinished, true)
.set(finished, LearningRecord::getFinishTime, recordDTO.getCommitTime())
.eq(LearningRecord::getId, oldRecord.getId())
.update();
if (!update){
throw new DbException("更新学习记录失败!");
}
// 清理redis缓存,让其与数据库同步,否则还要单独改是否第一次完成字段,比较麻烦
taskHandler.cleanRecordCache(recordDTO.getLessonId(), recordDTO.getSectionId());
return true;
}
如果结果集合中有新的字段,接受的实体类中没有,不用新增字段,直接用别的字段,给结果集的属性起别名代替即可。
比如统计数量 起个别名放到userid中
查询学习计划进度业务
1.获取当前用户id,查询本周学习计划总数量
public LearningPlanPageVO queryMyPlans(PageQuery query) {
// 1.获取当前登录用户id
Long userId = UserContext.getUser();
// todo 2.查询积分
// 3. 存在bug(课程过期) 查询本周学习计划总数据
QueryWrapper<LearningLesson> wrapper = new QueryWrapper<>();
wrapper.select("sum(week_freq) as plansTotal");
wrapper.eq("user_id",userId);
wrapper.in("status",LessonStatus.NOT_BEGIN,LessonStatus.LEARNING);
wrapper.eq("plan_status", PlanStatus.PLAN_RUNNING);
Map<String, Object> map = this.getMap(wrapper); // map 有可能为空
Integer plansTotal = 0;
if (map!=null && map.get("plansTotal")!=null){
plansTotal = Integer.valueOf(map.get("plansTotal").toString());
}
// 4 查询本周 已学习的计划总数据(这个用户在这段时间内完成的计划数)
LocalDate now = LocalDate.now();
LocalDateTime weekBeginTime = DateUtils.getWeekBeginTime(now);
LocalDateTime weekEndTime = DateUtils.getWeekEndTime(now);
Integer weekFinishedPlanNum = recordMapper.selectCount(Wrappers.<LearningRecord>lambdaQuery()
.eq(LearningRecord::getUserId, userId)
.eq(LearningRecord::getFinished, true)
.between(LearningRecord::getFinishTime, weekBeginTime, weekEndTime));
// 5 查询课表数据 分页查询 (这个用户在学习计划中的开始学习和没有开始学习的课表)
Page<LearningLesson> page = this.lambdaQuery()
.eq(LearningLesson::getUserId, userId)
.in(LearningLesson::getStatus, LessonStatus.NOT_BEGIN, LessonStatus.LEARNING)
.eq(LearningLesson::getPlanStatus, PlanStatus.PLAN_RUNNING)
.page(query.toMpPage("latest_learn_time", false));
List<LearningLesson> records = page.getRecords();
if (CollUtils.isEmpty(records)){
LearningPlanPageVO vo = new LearningPlanPageVO();
vo.setTotal(0L);
vo.setPages(0L);
vo.setList(CollUtils.emptyList());
return vo;
}
// 6 远程调用课程服务 获取课程信息
Set<Long> courseIds = records.stream().map(LearningLesson::getCourseId).collect(Collectors.toSet());
List<CourseSimpleInfoDTO> cinfos = courseClient.getSimpleInfoList(courseIds);
if (CollUtils.isEmpty(cinfos)){
throw new BizIllegalException("课程不存在");
}
//将cinfo list 结构转化为map <课程id,coursesimpleinfodto>
Map<Long, CourseSimpleInfoDTO> cInfoMap = cinfos.stream().collect(Collectors.toMap(CourseSimpleInfoDTO::getId, c -> c));
// 7 查询学习记录表 本周 当前用户下每一门课程下 已学习的小节数量
QueryWrapper<LearningRecord> recordQueryWrapper = new QueryWrapper<>();
recordQueryWrapper.select("lesson_id as lessonId","count(*) as userId");
recordQueryWrapper.eq("user_id",userId);
recordQueryWrapper.eq("finished",true);
recordQueryWrapper.between("finish_time",weekBeginTime,weekEndTime);
recordQueryWrapper.groupBy("lesson_id");
List<LearningRecord> learningRecords = recordMapper.selectList(recordQueryWrapper);
Map<Long, Long> courseWeekFinishNumMap = learningRecords.stream().collect(Collectors.toMap(LearningRecord::getLessonId, LearningRecord::getUserId));
// 8 封装vo返回
LearningPlanPageVO vo = new LearningPlanPageVO();
vo.setWeekTotalPlan(plansTotal);
vo.setWeekFinished(weekFinishedPlanNum);
ArrayList<LearningPlanVO> volist = new ArrayList<>();
for (LearningLesson record : records) {
LearningPlanVO planVO = BeanUtils.copyBean(record, LearningPlanVO.class);
CourseSimpleInfoDTO infoDTO = cInfoMap.get(record.getCourseId());
if (infoDTO!=null){
planVO.setCourseName(infoDTO.getName());
planVO.setSections(infoDTO.getSectionNum());
}
// map的方法 如果record.getId() 不存在 则以后面默认值为准,一句顶原来if else 判断
planVO.setWeekLearnedSections(courseWeekFinishNumMap.getOrDefault(record.getId(),0L).intValue());
volist.add(planVO);
}
return vo.pageInfo(page.getTotal(),page.getPages(),volist);
}
map方法的getordefault
如果不为空则为,为空则为第二个参数,然后转化为自己想要的类型
spring 定时任务
启动类开启任务调度
方法交给spring去管理
stream流
以主键和统计数进行收集
Map<Long, Long> courseWeekFinishNumMap = learningRecords.stream().collect(Collectors.toMap(LearningRecord::getLessonId, LearningRecord::getUserId));