評論系統(tǒng)數(shù)據(jù)庫設(shè)計及實現(xiàn)

評論系統(tǒng)數(shù)據(jù)庫設(shè)計及實現(xiàn)

需求分析

一般我們?yōu)g覽網(wǎng)站的時候經(jīng)常能看到如下圖的這種效果(圖片來自CSDN)

image

這種評論層層嵌套李剖,每個評論下面還掛著若干個對評論的回復(fù)。

這種結(jié)構(gòu)類似于樹狀結(jié)構(gòu)形真,用戶看起來一目了然祟滴,也是一種非常主流的評論系統(tǒng)設(shè)計。

數(shù)據(jù)庫設(shè)計

在以評論為主的樹形結(jié)構(gòu)中松申,數(shù)據(jù)庫的設(shè)計非常靈活灿里,可以是單表設(shè)計关炼,每個評論都有一個parent_id指向父評論。還可以分開為兩個表匣吊,評論一張表儒拂,對評論的回復(fù)是另一張表。

這里我使用的是單表設(shè)計色鸳。

數(shù)據(jù)表設(shè)計如下社痛。由于我開發(fā)的是一個新聞系統(tǒng),所以我就直接以項目舉例命雀。

表字段 字段說明
commentId 評論的id蒜哀,自增值,每個評論都對應(yīng)一個唯一的commentId
newsId 評論所對應(yīng)的新聞的id
content 評論的內(nèi)容
userId 發(fā)出該評論用戶的id
parentId 指向父評論的id,如果不是對評論的回復(fù),那么該值為null
date 評論產(chǎn)生日期

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;

實現(xiàn)

  • 查詢語句:
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

為了減少數(shù)據(jù)庫查詢次數(shù)吏砂,直接一次將一個新聞下的所有評論都查詢了出來撵儿,然后通過程序來編排評論的顯示結(jié)構(gòu)乘客。通過適當(dāng)?shù)娜哂鄟硖岣咝阅芤彩浅S玫膬?yōu)化手段之一

  • 評論的實體類

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;
}

這里給出一段通過程序來組織所有評論的代碼(為了文章的精簡,只寫邏輯相關(guān)的代碼)

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,當(dāng)然break也可以提高算法效率
                        break;
                    }
                }
                if (!foundParent) {
                    throw new RuntimeException("can not find the parent comment");
                }
            }
        }
        return comments;

最終形成的效果圖。


image

接口返回的數(shù)據(jù)如下:

{
    "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": "如果無法有尊嚴(yán)的活著报亩,就難受",
                                    "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": "增大網(wǎng)",
            "author_url": "../../images/gravatar.png",
            "date": "2019-04-08",
            "content": "送你一片大海掸哑,讓你一帆風(fēng)順;送你一個太陽零远,讓你熱情奔放苗分;送你一份真誠,祝你開心快樂牵辣;送你一份祝福摔癣,讓你快樂天天!",
            "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": []
                }
            ]
        }
    ]
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末纬向,一起剝皮案震驚了整個濱河市择浊,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌逾条,老刑警劉巖琢岩,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異师脂,居然都是意外死亡担孔,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進(jìn)店門危彩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來攒磨,“玉大人,你說我怎么就攤上這事汤徽∶溏郑” “怎么了?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵谒府,是天一觀的道長拼坎。 經(jīng)常有香客問我浮毯,道長,這世上最難降的妖魔是什么泰鸡? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任债蓝,我火速辦了婚禮,結(jié)果婚禮上盛龄,老公的妹妹穿的比我還像新娘饰迹。我一直安慰自己,他們只是感情好余舶,可當(dāng)我...
    茶點故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布啊鸭。 她就那樣靜靜地躺著,像睡著了一般匿值。 火紅的嫁衣襯著肌膚如雪赠制。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天挟憔,我揣著相機與錄音钟些,去河邊找鬼。 笑死绊谭,一個胖子當(dāng)著我的面吹牛政恍,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播达传,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼抚垃,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了趟大?” 一聲冷哼從身側(cè)響起鹤树,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎逊朽,沒想到半個月后罕伯,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡叽讳,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年追他,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片岛蚤。...
    茶點故事閱讀 38,617評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡邑狸,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出涤妒,到底是詐尸還是另有隱情单雾,我是刑警寧澤仇穗,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布筝野,位于F島的核電站嗅钻,受9級特大地震影響昭灵,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜渐逃,卻給世界環(huán)境...
    茶點故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一够掠、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧茄菊,春花似錦疯潭、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至畜普,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間群叶,已是汗流浹背吃挑。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留街立,地道東北人舶衬。 一個月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像赎离,于是被迫代替她去往敵國和親逛犹。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,486評論 2 348

推薦閱讀更多精彩內(nèi)容