一、前言
最近业务有涉及收藏模块的设计与实现,需要在基础的功能 上额外实现多一个收藏功能。
二、需求
需求场景:
- 多个不同的业务。 (这里就举掘金的例子 ,以下也是;例如:文章、小册、沸点等等)
- 不同用户的收藏独立化。
- 统计所有用户和当前用户的收藏情况。
- 展示收藏分类对应详细内容的情况。(如:收藏文章/小册/沸点等的详细内容)
三、设计思路
经过了查询了部分资料,最终发现并决定用额外一张收藏表 就能实现起来。
(一)数据库 mysql
这张表的字段就需要有业务id ,业务类型 ,用户id。
因此,大概结构类型就为:
sql 生成表和数据脚本(模拟数据)如下:
sql
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for t_collect
-- ----------------------------
DROP TABLE IF EXISTS `t_collect`;
CREATE TABLE `t_collect` (
`id` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'id',
`business_id` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '业务id',
`user_id` varchar(36) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '用户id',
`business_type` tinyint(4) NULL DEFAULT 0 COMMENT '业务类型 (1:文章;2:小册;3:沸点 )',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of t_collect
-- ----------------------------
INSERT INTO `t_collect` VALUES ('1', 'post_1', 'user_1', 1);
INSERT INTO `t_collect` VALUES ('2', 'post_2', 'user_1', 1);
INSERT INTO `t_collect` VALUES ('3', 'post_3', 'user_2', 1);
INSERT INTO `t_collect` VALUES ('4', 'post_3', 'user_1', 1);
INSERT INTO `t_collect` VALUES ('5', 'book_1', 'user_1', 2);
INSERT INTO `t_collect` VALUES ('6', 'book_2', 'user_3', 2);
INSERT INTO `t_collect` VALUES ('7', 'dot_1', 'user_2', 3);
INSERT INTO `t_collect` VALUES ('8', 'dot_2', 'user_2', 3);
INSERT INTO `t_collect` VALUES ('9', 'dot_2', 'user_3', 3);
INSERT INTO `t_collect` VALUES ('10', 'dot_3', 'user_3', 3);
SET FOREIGN_KEY_CHECKS = 1;
(二)业务代码 mysql
有表也有数据,就先根据业务用 mysql 语句去实现。
根据需求场景来说,具体化之后的实现是需要有:
① 当前用户的收藏对应业务;
② 各业务的收藏排行榜;
③ 当前用户对应的业务收藏详细内容的情况;
① 当前用户的收藏对应业务
sql
-- 当前用户的收藏对应业务(当前查询 user_id 为"user_1")
SELECT business_type AS type, COUNT(1) AS count
FROM t_collect
WHERE user_id = 'user_1'
GROUP BY business_type;
结果
② 各业务的收藏排行榜
sql
-- 所有业务的收藏排行榜
SELECT user_id, business_type type, COUNT(1) count
FROM t_collect
GROUP BY user_id, business_type
ORDER BY business_type, count DESC;
-- 根据类型业务的收藏排行榜
SELECT business_type AS type, user_id, COUNT(1) AS count
FROM t_collect
WHERE business_type = 1
GROUP BY user_id;
结果
③ 当前用户对应的业务收藏详细内容的情况
这里是需要查询当前用户 和对应业务类型 匹配对应的收藏数据,再根据查询结果的业务 id 去查询对应业务表的数据即可查询详情内容。
sql
-- 查询当前用户与业务类型对应的收藏记录(主要查出业务 id )
SELECT business_type AS type, user_id, business_id
FROM t_collect
WHERE business_type = 1
AND user_id = "user_1";
-- 再根据 business_type 和 business_id 在 java 代码业务类型枚举中查询对应业务表的数据
-- ...
(三)业务代码 java
以下是基于 MyBatis-Plus 代码(且会以 jdk 8 lambda 表达式为主)
CollectTypeEnum.java
java
/**
* @Author nanfnagzhe
* @Description TODO 收藏对应业务类型的枚举类
* @Date 2023/9/17
**/
public enum CollectTypeEnum {
/**
* 业务类型 (1:文章;2:小册;3:沸点 )
*/
POST(1, "文章"),
BOOK(2, "小册"),
DOT(3, "沸点"),
;
private Integer code;
private String text;
CollectTypeEnum(Integer code, String text) {
this.code = code;
this.text = text;
}
public Integer getCode() {
return code;
}
public String getText() {
return text;
}
public Integer code() {
return code;
}
/**
* 根据 code 获取对应的内容(返回给前端)
*/
public static String text(Integer code) {
for (CollectTypeEnum one : CollectTypeEnum.values()) {
if (one.code().equals(code)) {
return one.getText();
}
}
return null;
}
}
代码因为和 sql 语句实现更加方便,查询出结果后,主要展示枚举类对应的使用。
CollectServiceImpl.java
java
// ...
/**
* TODO: 当前用户的收藏对应业务
*
* @Author nanfangzhe
* @Date 2023/9/17
**/
@Override
public Map<String, Object> getListByType(Integer type) {
Map<String, Object> resMap = new HashMap<>();
QueryWrapper<CollectVo> wrapper = new QueryWrapper<>();
wrapper.eq("user_id", "user_1");
wrapper.eq("business_type", type);
wrapper.groupBy("business_type");
List<CollectVo> list = collectMapper.selectList(wrapper);
list.forEach(one -> {
one.setBusinessName(CollectTypeEnum.text(one.getBusinessType()));
});
resMap.put("data", list);
return resMap;
}
// ...
// 其他代码实现类似,主要围绕枚举展示方便使用,反馈给前端数据。
/**
* TODO: 当前用户的收藏对应业务
*
* @Author nanfangzhe
* @Date 2023/9/17
**/
@Override
public Map<String, Object> getDetailsListByType(Integer type) {
Map<String, Object> resMap = new HashMap<>();
QueryWrapper<CollectVo> wrapper = new QueryWrapper<>();
wrapper.eq("user_id", "user_1");
wrapper.eq("business_type", type);
wrapper.groupBy("business_type");
List<CollectVo> list = collectMapper.selectList(wrapper);
// 获取对应业务 id List
List<String> businessIdList = list.stream().map(CollectVo::getBusinessId).collect(Collectors.toList());
Object data = new Object();
if(type.equals(CollectTypeEnum.POST.code())){
// 文章业务处理
data = getPostList(businessIdList);
} else if (type.equals(CollectTypeEnum.DOT.code())) {
// 文章业务处理
data = getDotList(businessIdList);
}else if (type.equals(CollectTypeEnum.DOT.code())) {
// 文章业务处理
data = getBookList(businessIdList);
}
return resMap;
}
private Object getPostList(List<String> businessIdList){
// 文章业务对应的处理
return postService.selectBatchIds(businessIdList);
}
private Object getBookList(List<String> businessIdList){
// 小册业务对应的处理
return bookService.selectBatchIds(businessIdList);
}
private Object getDotList(List<String> businessIdList){
// 沸点业务对应的处理
return dotService.selectBatchIds(businessIdList);
}
总结
通过本篇学习,对枚举使用有一定明确,先分析业务需求,在查询的结果,进行枚举再细分处理;返回的结果再进行对其完善处理,最终完成业务需求。(即剩下的问题交给前端 ~ )
文章小尾巴
文章小尾巴(点击展开)
文章写作、模板、文章小尾巴可参考:《写作"小心思"》
感谢你看到最后,最后再说两点~
①如果你持有不同的看法,欢迎你在文章下方进行留言、评论。
②如果对你有帮助,或者你认可的话,欢迎给个小点赞,支持一下~
(文章内容仅供学习参考,如有侵权,非常抱歉,请立即联系作者删除。)