评论系统数据库设计及实现

评论系统数据库设计及实现

需求分析

一般我们浏览网站的时候经常能看到如下图的这种效果(图片来自CSDN)

image

这种评论层层嵌套,每个评论下面还挂着若干个对评论的回复。

这种结构类似于树状结构,用户看起来一目了然,也是一种非常主流的评论系统设计。

数据库设计

在以评论为主的树形结构中,数据库的设计非常灵活,可以是单表设计,每个评论都有一个parent_id指向父评论。还可以分开为两个表,评论一张表,对评论的回复是另一张表。

这里我使用的是单表设计。

数据表设计如下。由于我开发的是一个新闻系统,所以我就直接以项目举例。

表字段 字段说明
commentId 评论的id,自增值,每个评论都对应一个唯一的commentId
newsId 评论所对应的新闻的id
content 评论的内容
userId 发出该评论用户的id
parentId 指向父评论的id,如果不是对评论的回复,那么该值为null
date 评论产生日期

SQL语句:

评论表:

create table if not exists comments
(
    commentId bigint auto_increment primary key,
    newsId    bigint not null,
    parentId  bigint,
    content   text   not null,
    userId    bigint not null,
    date      timestamp default current_timestamp(),
    foreign key (parentID) references comments (commentId),
    foreign key (userID) references users (userId),
    foreign key (newsID) references news (newsId)
) charset = utf8mb4;

实现

  • 查询语句:
SELECT a.commentId,a.newsId,a.parentId,a.newsId,b.nickname,b.avatar,a.content,a.date
        FROM comments AS a,users AS b WHERE a.newsId=#{newsId} AND a.userId=b.userId

为了减少数据库查询次数,直接一次将一个新闻下的所有评论都查询了出来,然后通过程序来编排评论的显示结构。通过适当的冗余来提高性能也是常用的优化手段之一

  • 评论的实体类

import lombok.Data;
import java.util.Date;
import java.util.List;

@Data
public class Comment {
    Long commentId;
    Long newsId;
    Long parentId;
    Long userId;
    String nickname;
    String avatar;
    String content;
    Date date;
    List<Comment> child;
}

这里给出一段通过程序来组织所有评论的代码(为了文章的精简,只写逻辑相关的代码)

public List<Comment> getComments(Long newsId) {
        List<Comment> allComments = commentMapper.getComments(newsId);
        if (allComments == null || allComments.size() == 0) {
            return new ArrayList<>();
        }
        List<Comment> comments = new ArrayList<>();
        List<Comment> parents = new ArrayList<>();
        for (Comment comment : allComments) {
            if (comment.getParentId()==null) {
                comments.add(comment);
                parents.add(comment);
            } else {
                boolean foundParent=false;
                for (Comment parent : parents) {
                    if (comment.getParentId() == parent.getCommentId()) {
                        if (parent.getChild() == null) {
                            parent.setChild(new ArrayList<>());
                        }
                        parent.getChild().add(comment);
                        parents.add(comment);
                        foundParent=true;
                        //如果对list迭代过程中同时修改list,会报java.util.ConcurrentModificationException 的异常,所以我们需要break,当然break也可以提高算法效率
                        break;
                    }
                }
                if (!foundParent) {
                    throw new RuntimeException("can not find the parent comment");
                }
            }
        }
        return comments;

最终形成的效果图。


image

接口返回的数据如下:

{
    "code": "success",
    "message": "获取评论成功",
    "status": "200",
    "data": [
        {
            "id": "236051",
            "author_name": "Jianbo",
            "author_url": "https://wx.qlogo.cn/mmopen/vi_32/Qib5jkFMntPJnT8b2nyzKicoYSuXLeyl07ia1dianxx1fWcic9hJL4UOEuIJvoWWbx7IFia3olUGqiabZvTe0dmeFBicHQ/132",
            "date": "6小时前",
            "content": "tt",
            "userid": "24",
            "child": []
        },
        {
            "id": "236028",
            "author_name": "起航",
            "author_url": "https://wx.qlogo.cn/mmopen/vi_32/7Aq39lKL2jxoWSMgbiaYkQzOR0mOMTm2TLjVhRicYaFXAzg20I8gpcqySYYYQMWG60p8r5kibG3ibiav3CC8Bzibjblw/132",
            "date": "2019-04-11",
            "content": "很朴实的文字,又让人感动唏嘘",
            "formId": null,
            "userid": "9676",
            "child": [
                {
                    "id": "236032",
                    "author_name": "Jianbo",
                    "author_url": "https://wx.qlogo.cn/mmopen/vi_32/Qib5jkFMntPJnT8b2nyzKicoYSuXLeyl07ia1dianxx1fWcic9hJL4UOEuIJvoWWbx7IFia3olUGqiabZvTe0dmeFBicHQ/132",
                    "date": "2天前",
                    "content": ":-)",
                    "userid": "24",
                    "child": [
                        {
                            "id": "236040",
                            "author_name": "God loves me",
                            "author_url": "https://wx.qlogo.cn/mmopen/vi_32/QTU6iasloiaun5OX6ZcZB964vhHLAc5RuIf8kMR3nwIXvy0HibYOe9RJ9o8escDOIj7MB1vica5ibZ2XSDXIibfQMsJA/132",
                            "date": "1天前",
                            "content": "为什么有人会选择安乐死呢,活着难道比不上痛苦吗",
                            "userid": "9663",
                            "child": [
                                {
                                    "id": "236042",
                                    "author_name": "Jianbo",
                                    "author_url": "https://wx.qlogo.cn/mmopen/vi_32/Qib5jkFMntPJnT8b2nyzKicoYSuXLeyl07ia1dianxx1fWcic9hJL4UOEuIJvoWWbx7IFia3olUGqiabZvTe0dmeFBicHQ/132",
                                    "date": "1天前",
                                    "content": "如果无法有尊严的活着,就难受",
                                    "child": []
                                }
                            ]
                        }
                    ]
                }
            ]
        },
        {
            "id": "236024",
            "author_name": "倡萌",
            "author_url": "../../images/gravatar.png",
            "date": "2019-04-11",
            "content": "每个人都有自己难以忘怀的过往,昨天今天明天,努力过好每一天!",
            "userid": "0",
            "child": [
                {
                    "id": "236041",
                    "author_name": "Jianbo",
                    "author_url": "https://wx.qlogo.cn/mmopen/vi_32/Qib5jkFMntPJnT8b2nyzKicoYSuXLeyl07ia1dianxx1fWcic9hJL4UOEuIJvoWWbx7IFia3olUGqiabZvTe0dmeFBicHQ/132",
                    "date": "1天前",
                    "content": "过好今天,很重要",
                    "userid": "24",
                    "child": []
                }
            ]
        },
        {
            "id": "236018",
            "author_name": "Jielinfan",
            "author_url": "https://wx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTJBXIvvpMo5nXdlk6Mxwia9chS9E8VHGEQbDmyEAx8opRibztDzmpGHpbC3lR5vh8l4fsScZWoyEWyQ/132",
            "date": "2019-04-08",
            "content": "祝福老哥。",
            "userid": "280",
            "child": [
                {
                    "id": "236019",
                    "author_name": "Jianbo",
                    "author_url": "https://wx.qlogo.cn/mmopen/vi_32/Qib5jkFMntPJnT8b2nyzKicoYSuXLeyl07ia1dianxx1fWcic9hJL4UOEuIJvoWWbx7IFia3olUGqiabZvTe0dmeFBicHQ/132",
                    "date": "2019-04-09",
                    "content": ":-)",
                    "userid": "24",
                    "child": []
                }
            ]
        },
        {
            "id": "236017",
            "author_name": "增大网",
            "author_url": "../../images/gravatar.png",
            "date": "2019-04-08",
            "content": "送你一片大海,让你一帆风顺;送你一个太阳,让你热情奔放;送你一份真诚,祝你开心快乐;送你一份祝福,让你快乐天天!",
            "formId": null,
            "userid": "0",
            "child": []
        },
        {
            "id": "236011",
            "author_name": "今日新闻",
            "author_url": "../../images/gravatar.png",
            "date": "2019-04-07",
            "content": "文章不错非常喜欢",
            "userid": "0",
            "child": [
                {
                    "id": "236052",
                    "author_name": "Jianbo",
                    "author_url": "https://wx.qlogo.cn/mmopen/vi_32/Qib5jkFMntPJnT8b2nyzKicoYSuXLeyl07ia1dianxx1fWcic9hJL4UOEuIJvoWWbx7IFia3olUGqiabZvTe0dmeFBicHQ/132",
                    "date": "6小时前",
                    "content": "谢谢",
                    "userid": "24",
                    "child": []
                }
            ]
        }
    ]
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,542评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,596评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,021评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,682评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,792评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,985评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,107评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,845评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,299评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,612评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,747评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,441评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,072评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,828评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,069评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,545评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,658评论 2 350

推荐阅读更多精彩内容