前言讲述一段血泪史,有血,有泪,有市。
前言:公司做的是一个“线下阅读,线上测评”的阅读教育平台,我负责的其中一块就是班级圈动态查询,主要的数据表涉及到1动态索引表(将所有动态记录但不记录具体信息),2-多个动态具体信息表(比如购课动态信息表,朗读动态信息表等)。看上去比较简单的逻辑可把我难倒了,差点没哭,前后大改就改了三次,小改不计其数。最尴尬的是最后的修订版是在我们经理的引导下完成的。话不多说,进入正题。
正文:
思路
1.查询班级的动态索引(查动态索引表)。
2.根据ModuleType(动态类型)分类,将各类对应的的的moduleId(动态ID)集中到一个容器(这个容器在第3步讲)。
3.创建一个容器存的的moduleId(动态ID)集合,ModuleType(动态类型)分类,索引(动态的位置)集合。
解释第3步:为什么要存指标呢这是关键,就是要记住这条动态的位置比如说,在执行完第一步之后,查询出来的数据是“
{[的moduleId = 1,ModuleType =“朗读”],[的moduleId = 2,ModuleType =“购课”],[的moduleId = 1,ModuleType =“朗读”],...}“,那么第2步就要这样分“{[ModuleType =”朗读“,ModuleIds = [1,3],指数法= [0,2]],ModuleType =”购课“,ModuleIds = [2],指数法= [1 ]}”。这是最后数据还原必要的条件。
4.根据索引表里的ModuleType(动态类型)和ModuleIds(动态ID集合)到各个动态表里查询出具体动态信息。这么查大家都明白减少与数据库的交互,调高效率,尤其是高并发的系统,一定要这样做。(由于动态索引表查的时候是按照时间倒序,所以分开查询动态具体内容的时候也要倒序,要不然还原数据的时候会混乱)
5.还原数据,根据指数动态的位置信息将查询出来的数据按照最初的顺序还原。
代码 - 容器
package com.syzton.reading.util;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import com.syzton.reading.beans.clazz.DynamicModel;
public class DynamicTypeModal {
/**
* 模型类型标识
*/
private String key;
/**
* 数据长度
*/
private int size = 0;
/**
* 位置索引
*/
private List indexs = new ArrayList<>();
/**
* 模型数据id列表
*/
private List ids =new ArrayList<>();
/**
* 设置数据
* @param mId
* @param index
*/
public void setModeData(String mId,int index){
this.ids.add(mId);
this.indexs.add(index);
this.size = this.ids.size();
}
/**
* 填充数据到返回结果集合中
* @param result
* @param serchData
* @return
*/
public boolean fillDataToResult(List
代码 - 具体业务
package com.syzton.reading.services.student.clazz;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.Session;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSON;
import com.syzton.common.PubFun;
import com.syzton.common.db.Paging;
import com.syzton.common.db.SqlQuery;
import com.syzton.common.db.bean.Loginer;
import com.syzton.common.web.beans.RequestParamas;
import com.syzton.common.web.beans.RequestResult;
import com.syzton.reading.beans.clazz.DynamicModel;
import com.syzton.reading.services.BaseService;
import com.syzton.reading.util.Constants;
import com.syzton.reading.util.DynamicTypeModal;
@Service
public class DynamicServiceImpl extends BaseService implements DynamicService {
@Override
public RequestResult queryDynamicList(RequestParamas params) {
RequestResult result = new RequestResult();
if(!params.isLogined()){
result.addState(false);
result.addStateMsg("请登录后查看");
return result;
}
Loginer loginer = params.getLoginer();
Session session = this.getPDReadingSession(true);
Long userId = loginer.getUserId();
Long clazzId = PubFun.convert2Long(loginer.getClazzId(), 0L);
Long campusId = PubFun.convert2Long(loginer.getCampusId(), 0L);
long gradeId = loginer.getGradeId();
Paging paging = params.createPaging();
//查询班级动态索引
List dynamicModelList = SqlQuery.create("clazz/getDynamicList.sls")
.setParam("clazzId", clazzId)
.setParam("userId", userId)
.execSQLView(session, paging);
if(CollectionUtils.isEmpty(dynamicModelList)){
return result.addState(false).addStateMsg("暂无动态");
}
DynamicTypeModal dynamicTypeModalPingLun = new DynamicTypeModal();
DynamicTypeModal dynamicTypeModalLangDu = new DynamicTypeModal();
DynamicTypeModal dynamicTypeModalKeCheng = new DynamicTypeModal();
DynamicTypeModal dynamicTypeModalDuShu = new DynamicTypeModal();
DynamicTypeModal dynamicTypeModalXunZhang = new DynamicTypeModal();
DynamicTypeModal dynamicTypeModalHuiFu = new DynamicTypeModal();
//将各个模块的id集合封装
for (int i = 0; i < dynamicModelList.size(); i++) {
String moduleType = PubFun.convert2String(dynamicModelList.get(i).get("MODULETYPE"), "");
String moduleId = PubFun.convert2String(dynamicModelList.get(i).get("MODULEID"),"");
//将动态ID按类型封装
if(Constants.DYNAMIC_INDEX_MODULETYPE_BIJI.equals(moduleType)){
continue;
}else if(Constants.DYNAMIC_INDEX_MODULETYPE_TIAOZHAN.equals(moduleType)){
continue;
}else if(Constants.DYNAMIC_INDEX_MODULETYPE_PINGLUN.equals(moduleType)){
dynamicTypeModalPingLun.setKey(moduleType);
dynamicTypeModalPingLun.setModeData(moduleId, i);
continue;
}else if(Constants.DYNAMIC_INDEX_MODULETYPE_LANGDU.equals(moduleType)){
dynamicTypeModalLangDu.setKey(moduleType);
dynamicTypeModalLangDu.setModeData(moduleId, i);
continue;
}else if(Constants.DYNAMIC_INDEX_MODULETYPE_KECHENG.equals(moduleType)){
dynamicTypeModalKeCheng.setKey(moduleType);
dynamicTypeModalKeCheng.setModeData(moduleId, i);
continue;
}else if(Constants.DYNAMIC_INDEX_MODULETYPE_BOOK.equals(moduleType)){
dynamicTypeModalDuShu.setKey(moduleType);
dynamicTypeModalDuShu.setModeData(moduleId,i);
continue;
}else if(Constants.DYNAMIC_INDEX_MODULETYPE_XUNZHANG.equals(moduleType)){
dynamicTypeModalXunZhang.setKey(moduleType);
dynamicTypeModalXunZhang.setModeData(moduleId, i);
continue;
}else if(Constants.DYNAMIC_INDEX_MODULETYPE_HUIFU.equals(moduleType)){
dynamicTypeModalHuiFu.setKey(moduleType);
dynamicTypeModalHuiFu.setModeData(moduleId, i);
}
}
//动态内容查询
//朗读动态
if(Constants.DYNAMIC_INDEX_MODULETYPE_LANGDU.equals(dynamicTypeModalLangDu.getKey())){
List langDuDynamicModels = SqlQuery.create("clazz/getDynamicContentLangDuList.sls")
.setParam("dynReadingId", dynamicTypeModalLangDu.getIds())
.setParam("userId", userId)
.setParam("postType", Constants.POST_TYPE_RADIO)
.getListView(session);
dynamicTypeModalLangDu.fillDataToResult(dynamicModelList, langDuDynamicModels);
}
if(Constants.DYNAMIC_INDEX_MODULETYPE_KECHENG.equals(dynamicTypeModalKeCheng.getKey())){
//购课动态
List keChengDynamicModels = SqlQuery.create("clazz/getDynamicContentCourseList.sls")
.setParam("dynCourseIds", dynamicTypeModalKeCheng.getIds())
.setParam("userId", userId)
.setParam("productType", Constants.ORDER_PRODUCT_TYPE_COURSE)
.setParam("orderState", Constants.ORDER_STATE_PAID)
.getListView(session);
dynamicTypeModalKeCheng.fillDataToResult(dynamicModelList, keChengDynamicModels);
}
if(Constants.DYNAMIC_INDEX_MODULETYPE_BOOK.equals(dynamicTypeModalDuShu.getKey())){
//读书动态
List bookDynamicModels = SqlQuery.create("clazz/getDynamicContentBookList.sls")
.setParam("dynBookIds", dynamicTypeModalDuShu.getIds())
.setParam("verifiedState",1)
.setParam("userId", userId)
.getListView(session);
dynamicTypeModalDuShu.fillDataToResult(dynamicModelList, bookDynamicModels);
}
if(Constants.DYNAMIC_INDEX_MODULETYPE_XUNZHANG.equals(dynamicTypeModalXunZhang.getKey())){
//勋章动态
List medalDynamicModels = SqlQuery.create("clazz/getDynamicContentMedalList.sls")
.setParam("dynMedalIds", dynamicTypeModalXunZhang.getIds())
.setParam("userId", userId)
.getListView(session);
dynamicTypeModalXunZhang.fillDataToResult(dynamicModelList, medalDynamicModels);
}
if(Constants.DYNAMIC_INDEX_MODULETYPE_HUIFU.equals(dynamicTypeModalHuiFu.getKey())){
//回复动态
List replyDynamicModels = SqlQuery.create("clazz/getDynamicContentReplyList.sls")
.setParam("dynReplyIds", dynamicTypeModalHuiFu.getIds())
.setParam("userId", userId)
.setParam("replyModuleType", Constants.TB_RESOURCE_MODULE_TYPE)
.getListView(session);
dynamicTypeModalHuiFu.fillDataToResult(dynamicModelList, replyDynamicModels);
}
if(Constants.DYNAMIC_INDEX_MODULETYPE_PINGLUN.equals(dynamicTypeModalPingLun.getKey())){
//评论动态
List pingLunDynamicModels = SqlQuery.create("clazz/getDynamicContentPingLunList.sls")
.setParam("dynPingLunIds", dynamicTypeModalPingLun.getIds())
.setParam("userId", userId)
.setParam("leadingTopicModuleType", Constants.TB_RESOURCE_MODULE_LEADING_TOPIC)
.getListView(session);
for (int i = 0; i < pingLunDynamicModels.size(); i++) {
Long id = PubFun.convert2Long(pingLunDynamicModels.get(i).get("POSTID"), 0L);
//查询针对话题的回复集合
List replyDynamicModel = SqlQuery.create("clazz/getDynamicContentReplyListByPostId.sls")
.setParam("postIdList", id)
.setParam("userId", userId)
.setParam("replyModuleType", Constants.TB_RESOURCE_MODULE_TYPE)
.getListView(session);
//查询针对话题的回复数量
String replyNums = SqlQuery.create("clazz/queryDynamicPostReplyNum.sls")
.setParam("postIdList", id)
.getOneValue(session);
replyNums = StringUtils.isBlank(replyNums) ? "0" : replyNums;
pingLunDynamicModels.get(i).put("DYNAMICMODELS",replyDynamicModel);
pingLunDynamicModels.get(i).put("POSTREPLYNUM",replyNums);
}
dynamicTypeModalPingLun.fillDataToResult(dynamicModelList, pingLunDynamicModels);
}
String dynamicModelString = JSON.toJSONString(dynamicModelList);
List resultList = JSON.parseArray(dynamicModelString, DynamicModel.class);
result.addJSONData(resultList);
result.addJSONPagingData(paging);
result.addState(true);
result.addStateMsg("班级动态查询成功");
return result;
}
}
代码 - 动态信息实体类
package com.syzton.reading.beans.clazz;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import com.syzton.reading.beans.BaseBean;
import com.syzton.reading.util.OSSStyleUtil;
/**
* 班级动态模型
* @author lenovo
*
*/
public class DynamicModel extends BaseBean {
/**
*
*/
private static final long serialVersionUID = -415241041468321067L;
private String moduleId;
private String moduleType;
private String author;
private String behavior;
private String bookId;
private String bookName;
private String content;
//课程ID
private String course;
private String courseName;
private String likeNum;
private String pictureUrl;
private String cover;
private String resourcePath;
private String time;
private String title;
private String userId;
private String userName;
private String userPicture;
private String dynamicId;
private String duration;
private String timeDifference;
private String postId;
private String transversePic;
private String verticalPic;
private String isLike;//用户是否点赞
//话题或回复的内容的类型(音频,文字)
private String contentType;
//针对回复对应的话题的类型
private String postContentType;
//针对回复对应的话题的内容
private String postContent;
//是否倒赞
private String isNoLike;
//针对话题的回复数量
private String postReplyNum;
//书籍类型
private String bookClassify;
//子类型
private String postSubType;
//晨读ID
private String taskQuestionId;
private String picture;
public String getPicture() {
return picture;
}
public void setPicture(String picture) {
if(StringUtils.isNotBlank(picture)){
picture = OSSStyleUtil.processBookPicBean(picture, true);
setPictureUrl(picture);
}
this.picture = picture;
}
public String getCover() {
return cover;
}
public void setCover(String cover) {
if(StringUtils.isNotBlank(cover)){
cover = OSSStyleUtil.processBookPicBean(cover, false);
setPictureUrl(cover);
}
this.cover = cover;
}
public String getTaskQuestionId() {
return taskQuestionId;
}
public void setTaskQuestionId(String taskQuestionId) {
this.taskQuestionId = encryptField(taskQuestionId);
}
public String getPostSubType() {
return postSubType;
}
public void setPostSubType(String postSubType) {
this.postSubType = postSubType;
}
public String getBookClassify() {
return bookClassify;
}
public void setBookClassify(String bookClassify) {
this.bookClassify = bookClassify;
}
public String getPostReplyNum() {
return postReplyNum;
}
public void setPostReplyNum(String postReplyNum) {
this.postReplyNum = postReplyNum;
}
public String getIsNoLike() {
return isNoLike;
}
public void setIsNoLike(String isNoLike) {
this.isNoLike = isNoLike;
}
public String getPostContent() {
return postContent;
}
public void setPostContent(String postContent) {
this.postContent = kwSeeker(postContent);
}
public String getPostContentType() {
return postContentType;
}
public void setPostContentType(String postContentType) {
this.postContentType = postContentType;
}
public String getContentType() {
return contentType;
}
public void setContentType(String contentType) {
this.contentType = contentType;
}
public String getIsLike() {
return isLike;
}
public void setIsLike(String isLike) {
this.isLike = isLike;
}
public String getTransversePic() {
return transversePic;
}
public void setTransversePic(String transversePic) {
this.transversePic = OSSStyleUtil.processBookPicBean(transversePic, false);
}
public String getVerticalPic() {
return verticalPic;
}
public void setVerticalPic(String verticalPic) {
this.verticalPic = OSSStyleUtil.processBookPicBean(verticalPic, false);
}
private List dynamicModels = new ArrayList();
public List getDynamicModels() {
return dynamicModels;
}
public void setDynamicModels(List dynamicModels) {
this.dynamicModels = dynamicModels;
}
public DynamicModel() {
super();
// TODO Auto-generated constructor stub
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getBehavior() {
return behavior;
}
public void setBehavior(String behavior) {
this.behavior = behavior;
}
public String getBookId() {
return bookId;
}
public void setBookId(String bookId) {
if(StringUtils.isBlank(bookId)){
this.bookId = bookId;
}else{
this.bookId = this.encryptField(bookId);
}
}
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = kwSeeker(content);
}
public String getCourse() {
return course;
}
public void setCourse(String course) {
this.course = this.encryptField(course);
}
public String getCourseName() {
return courseName;
}
public void setCourseName(String courseName) {
this.courseName = courseName;
}
public String getLikeNum() {
return likeNum;
}
public void setLikeNum(String likeNum) {
this.likeNum = likeNum;
}
public String getPictureUrl() {
return pictureUrl;
}
public void setPictureUrl(String pictureUrl) {
this.pictureUrl = pictureUrl;
}
public String getResourcePath() {
return resourcePath;
}
public void setResourcePath(String resourcePath) {
this.resourcePath = OSSStyleUtil.processBookPicBean(resourcePath, false);
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = this.formatDate(time);
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = kwSeeker(title);
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = this.encryptField(userId);
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = kwSeeker(userName);
}
public String getUserPicture() {
return userPicture;
}
public void setUserPicture(String userPicture) {
this.userPicture = OSSStyleUtil.processBookPicBean(userPicture, false);
}
public String getModuleId() {
return moduleId;
}
public void setModuleId(String moduleId) {
this.moduleId = encryptField(moduleId);
}
public String getModuleType() {
return moduleType;
}
public void setModuleType(String moduleType) {
this.moduleType = moduleType;
}
public String getDynamicId() {
return dynamicId;
}
public void setDynamicId(String dynamicId) {
this.dynamicId = encryptField(dynamicId);
}
public String getDuration() {
return duration;
}
public void setDuration(String duration) {
this.duration = duration;
}
public String getTimeDifference() {
return timeDifference;
}
public void setTimeDifference(String timeDifference) {
this.timeDifference = timeDifference;
}
public String getPostId() {
return postId;
}
public void setPostId(String postId) {
this.postId = this.encryptField(postId);
}
}
交流WX:TG321371064
这也时的Java编程思想的典型的一种 - 分层 - 分空间。