評論回覆功能的數據庫設計(JAVA+MYSQl)

 1.概述

評論回覆功能是社交網站最基本的功能,本文主要講解評論留言的設計及實現。

需求:

  1. 用戶評論日記,回覆評論
  2. 顯示所有評論

2.數據庫設計

日記表:diary

用戶表:user

回覆表:reply

字段設計

private int id ; //回覆id (主鍵id)
private Integer diaryId; //日記id (關聯日記表)
private String text; //回覆內容 
private Integer userId;  //用戶id (關聯用戶表)
private Integer lastId;  //上一條回覆id (用於關聯回覆表,維護好每條評論的關係)

外鍵關係

講解:

通過last_id我們就能找到這條回覆是回覆的哪條評論或日記。

3.java實現思路

  1. 存儲我們使用鏈表,這樣可以一步一步找到最後一條回覆,應爲一條評論下可能有多人回覆,所以存儲下一個對象我們使用List來存儲(對象數組也行)
  2. 先查詢last_id爲null的數據,last_id爲null則說明這是日記的第一層評論。
  3. 查詢list_id不爲null的數據,last_id不爲null則說明這是回覆。
  4. 通過last_id找到對應的評論,回覆。添加到鏈表中。
  5. 打印

4.實現

示例數據庫數據

示例顯示(在web中顯示)

dao層使用的jpa.

實體類

1.Reply(評論實體類)

package com.ss.entity;

import lombok.Data;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Data
@Table(name = "reply")
public class Reply {
    @Id
    @GeneratedValue
    private int id ; //回覆id
    private Integer diaryId; //日記id
    private String text; //回覆內容
    private Integer userId;  //用戶id
    private Integer lastId;  //上一條回覆id
}

2.Node(鏈表結構)

package com.ss.entity;

import lombok.Data;

import java.util.ArrayList;
import java.util.List;

@Data
public class Node {

    public Node(){

    }

    /**
     * 構造函數
     * @param reply
     */
    public Node(Reply reply){
        this.id = reply.getId();
        this.diaryId = reply.getDiaryId();
        this.lastId = reply.getLastId();
        this.text = reply.getText();
        this.userId = reply.getUserId();
    }


    private int id ;
    private Integer diaryId;
    private String text;
    private Integer userId;
    private Integer lastId;
    //下一條回覆
    private List<Node> nextNodes = new ArrayList<Node>();


    /**
     * 將單個node添加到鏈表中
     * @param list
     * @param node
     * @return
     */
    public static boolean addNode(List<Node> list,Node node){
        for (Node node1 : list) {   //循環添加
            if (node1.getId()==node.getLastId()){   //判斷留言的上一段是都是這條留言
               node1.getNextNodes().add(node);   //是,添加,返回true;
               System.out.println("添加了一個");
               return true;
            }else{     //否則遞歸繼續判斷
                if (node1.getNextNodes().size()!=0)
                    if (Node.addNode(node1.getNextNodes(),node)){
                        return true;
                    }
            }
        }
        return false;
    }

    /**
     * 將查出來的lastId不爲null的回覆都添加到第一層Node集合中
     * @param firstList
     * @param thenList
     * @return
     */
    public static List addAllNode(List<Node> firstList,List<Reply> thenList){
        while (thenList.size()!=0){
            int size = thenList.size();
            for (int i = 0;i<size;i++){
                if (Node.addNode(firstList,new Node(thenList.get(i)))){
                    thenList.remove(i);
                    i--;
                    size--;
                }
            }
        }
        return firstList;
    }

    //打印
    public static void show(List<Node> list){
        for (Node node : list) {
            System.out.println(node.getUserId()+" 用戶回覆了你:"+node.getText());
            if (node.getNextNodes().size()!=0){
                Node.show(node.getNextNodes());
            }
        }
    }


}

3.Test方法

package com.ss.reply;

import com.ss.dao.ReplyRepository;
import com.ss.entity.Node;
import com.ss.entity.Reply;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.ArrayList;
import java.util.List;

@RunWith(SpringRunner.class)
@SpringBootTest
public class ReplyApplicationTests {

    @Autowired
    private ReplyRepository replyRepository;

    @Test
    public void contextLoads() {
        //查詢id爲6且lastId爲null的評論
        List firstList = replyRepository.findAllByDiaryIdAndLastIdNull(6);
        //查詢id爲6且LastId不爲null的評論
        List thenList = replyRepository.findAllByDiaryIdAndLastIdNotNull(6);
        //新建一個Node集合。
        ArrayList<Node> nodes = new ArrayList<>();
        //將第一層評論都添加都Node集合中
        for (Object o : firstList) {
            nodes.add(new Node((Reply) o));
        }
        //將回復添加到對應的位置
        List list = Node.addAllNode(nodes, thenList);
        System.out.println();
        //打印回覆鏈表
        Node.show(list);
    }

}

輸出結果

應爲沒有用關聯查詢,所以沒能顯示誰回覆的誰,但如果你已經能做到這裏,相信對你來說也不是難事了、

(沒有添加縮進符,所以顯示的一排,但和示例顯示的輸出順序是一樣的)

4.總結

在這個demo中,使用了遞歸插入鏈表,遞歸查詢鏈表。可能單看代碼理解有些困難,但主要的是數據庫設計,理解了數據庫設計,你自己也能寫出代碼來。

在web程序中你可以將最終得到的list<Node>鏈表返回給前端,前端通過自己寫一個js工具類,將list<Node>鏈表拆開顯示。

可能還有一個更簡單的方法,採用多對一的映射關係,讓數據庫通過外鍵關聯關係自動幫我們添加鏈表,但是你拆開鏈表的時候還是要用到遞歸。因爲現在對錶的映射關係不是太懂,所以在這先不說。以後有機會在來分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章