JAVA设计评论列表数据格式

需求:

用户可以评论,也可以回复评论,其他用户还可以评论、回复评论。

评论表实体(ArticleComment)

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;

/**
 * 评论表
 *
 * @author create by xiegege
 * @date 2021/6/17 16:00
 * 表中的levelFlag为评论等级,1表示一级,主要是文章的直接评论, 2表示二级,主要是主题评论的回复
 **/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("sys_article_comment")
@ApiModel(value = "ArticleComment对象", description = "评论表")
public class ArticleComment {

    @ApiModelProperty(value = "评论主键")
    @TableId("id")
    private Long id;

    @ApiModelProperty(value = "评论的文章Id")
    @TableField("article_id")
    private Long articleId;

    @ApiModelProperty(value = "父级评论Id")
    @TableField("parent_id")
    private Long parentId;

    @ApiModelProperty(value = "评论内容")
    @TableField("comment_content")
    private String commentContent;

    @ApiModelProperty(value = "评论等级")
    @TableField("level_flag")
    private Integer levelFlag;

    @ApiModelProperty(value = "点赞数")
    @TableField("upvote_count")
    private Integer upvoteCount;

    @ApiModelProperty(value = "是否置顶评论(0否,1是)")
    @TableField("whether_top")
    private Integer whetherTop;

    @ApiModelProperty(value = "用户Id")
    @TableField("user_id")
    private Long userId;

    @ApiModelProperty(value = "创建时间")
    @TableField("create_time")
    private String createTime;
}

建表sql语句

CREATE TABLE `sys_article_comment` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '评论主键',
  `article_id` bigint(20) NOT NULL COMMENT '评论的文章Id',
  `parent_id` bigint(20) NOT NULL COMMENT '父级评论Id',
  `comment_content` varchar(255) NOT NULL COMMENT '评论内容',
  `level_flag` int(10) NOT NULL COMMENT '评论等级:1主评论,2子评论',
  `upvote_count` int(10) NOT NULL DEFAULT '0' COMMENT '评论点赞数量',
  `whether_top` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否置顶评论(0否,1是)',
  `user_id` bigint(20) NOT NULL COMMENT '用户id',
  `create_time` datetime NOT NULL COMMENT '创建时间',
  PRIMARY KEY (`id`),
  KEY `index_id` (`article_id`,`parent_id`,`user_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;

我的表设计的很简单,因为本身项目就很简单,而且估计流量也不多,需求没有那么的大,别的话不说,如果你自己有更复杂的需求,可以自己再设计,我只是提供一个思路;

前端需求:
类似于这种:

/**
          张三 评论:你好
                谢哥哥 回复 张三: 你好
                    王五 回复 谢哥哥: 很好很好
                赵六 回复 张三:你好
          田七 评论:辣鸡
                谢哥哥 回复 田七: 你才是辣鸡
**/

抱歉,我以这种简陋的方式大家展示(手动捂脸)~

既然需求搞清楚了,基本就可以操作了,看这个前端需求,和一个数据结构有点像,就是树形结构,具体看下面的图(其实是手打的)

/**
*                                root
*                          /      |     \
*                         1       2      3
*                     / | | | \
*                    4  5 6 7  8
**/

所以就直接以树的形式进行组装就行了

评论表数据结构组装VO(CommentNodeTreeVo)

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.util.List;

/**
 * 评论表数据结构组装
 *
 * @author create by xiegege
 * @date 2021/6/17 16:10
 **/
@Data
public class CommentNodeTreeVo {

    @ApiModelProperty(value = "评论表id")
    private Long commentId;

    @ApiModelProperty(value = "用户Id")
    private Long userId;

    @ApiModelProperty(value = "用户头像")
    private String avatar;

    @ApiModelProperty(value = "用户昵称")
    private String nickName;

    @ApiModelProperty(value = "评论内容")
    private String commentContent;

    @ApiModelProperty(value = "点赞数")
    private Integer upvoteCount;

    @ApiModelProperty(value = "是否置顶评论(0否,1是)")
    private Integer whetherTop;

    @ApiModelProperty(value = "创建时间")
    private String createTime;

    private List<CommentNodeTreeVo> commentNodeTreeVos;
}

其中commentNodeTreeVos为root的下一层的节点集合;

Controller

import com.xgg.common.result.AjaxResult;
import com.xgg.javacode.model.vo.CommentNodeTreeVo;
import com.xgg.javacode.service.ArticleService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author xiegege
 * @date 2021/6/17 17:20
 */
@Api(tags = "文章相关api")
@RequestMapping("/article")
@RestController
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
@Slf4j
public class ArticleController {

    private final ArticleService articleService;

    @ApiOperation(value = "获取评论列表", response = CommentNodeTreeVo.class)
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "path", name = "articleId", dataType = "long", required = true, value = "文章id"),
            @ApiImplicitParam(paramType = "path", name = "pageNo", dataType = "int", required = true, value = "页码"),
            @ApiImplicitParam(paramType = "path", name = "pageSize", dataType = "int", required = true, value = "每页大小")
    })
    @GetMapping("findComment/{articleId}/{pageNo}/{pageSize}")
    public AjaxResult findComment(@PathVariable Long articleId, @PathVariable Integer pageNo, @PathVariable Integer pageSize) {
        return AjaxResult.success(articleService.findComment(articleId, pageNo, pageSize));
    }
}

Service(具体业务实现)

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.xgg.common.result.PageInfoResult;
import com.xgg.javacode.mapper.ArticleMapper;
import com.xgg.javacode.model.vo.CommentNodeTreeVo;
import com.xgg.javacode.service.ArticleService;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.List;

/**
 * @author xiegege
 * @date 2021/6/17 17:25
 */
@Service
@Transactional(rollbackFor = Exception.class)
@AllArgsConstructor
public class ArticleServiceImpl implements ArticleService {

    private final ArticleMapper articleMapper;

    @Override
    public PageInfoResult<CommentNodeTreeVo> findComment(Long articleId, Integer pageNo, Integer pageSize) {
        PageHelper.startPage(pageNo, pageSize);
        List<CommentNodeTreeVo> list = articleMapper.findComment(articleId);
        PageInfo<CommentNodeTreeVo> pageInfo = new PageInfo<>(list);
        List<CommentNodeTreeVo> pageInfoList = pageInfo.getList();
        for (CommentNodeTreeVo commentNodeTreeVo : pageInfoList) {
            deepSearch(commentNodeTreeVo);
        }
        return PageInfoResult.getPageInfoResult(pageInfo);
    }

    /**
     * 递归进行求树形节点
     *
     * @param commentNodeTreeVo 评论树
     */
    private void deepSearch(CommentNodeTreeVo commentNodeTreeVo) {
        if (commentNodeTreeVo != null) {
            // 查询子评论集合
            List<CommentNodeTreeVo> commentNodeTreeVos = articleMapper.findChildComment(commentNodeTreeVo.getCommentId());
            if (!CollectionUtils.isEmpty(commentNodeTreeVos)) {
                for (CommentNodeTreeVo vo : commentNodeTreeVos) {
                    commentNodeTreeVo.setCommentNodeTreeVos(commentNodeTreeVos);
                    deepSearch(vo);
                }
            }
        }
    }
}

Mapper.xml(sql语句)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xgg.javacode.mapper.ArticleMapper">

    <sql id="res">
        ac.id comment_id,
        u.user_id,
        u.avatar,
        u.nick_name,
        ac.comment_content,
        ac.upvote_count,
        ac.whether_top,
        DATE_FORMAT(ac.create_time,'%Y-%m-%d %H:%i') create_time
    </sql>

    <select id="findComment" resultType="com.xgg.javacode.model.vo.CommentNodeTreeVo">
        select
        <include refid="res"/>
        from sys_article_comment ac
        left join sys_user u on ac.user_id=u.user_id
        where ac.level_flag=1 and ac.article_id=#{articleId}
        order by ac.whether_top desc,ac.create_time desc
    </select>

    <select id="findChildComment" resultType="com.xgg.javacode.model.vo.CommentNodeTreeVo">
        select
        <include refid="res"/>
        from sys_article_comment ac
        left join sys_user u on ac.user_id=u.user_id
        where ac.level_flag=2 and ac.parent_id=#{commentId}
        order by ac.create_time desc
    </select>
</mapper>

自己简易封装返回的分页结果集(PageInfoResult)

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.pagehelper.PageInfo;
import lombok.Data;

import java.util.List;

/**
 * 分页结果集
 *
 * @author xiegege
 * @date 2020/4/17
 */
@Data
public class PageInfoResult<T> {

    /**
     * 当前页
     */
    private int pageNo;
    /**
     * 当前页的数量
     */
    private int currentPageNum;
    /**
     * 数据总数量
     */
    private long total;
    /**
     * 总页数
     */
    private int totalPages;
    /**
     * 结果集
     */
    private List<T> list;

    public static PageInfoResult getPageInfoResult(PageInfo pageInfo) {
        PageInfoResult result = new PageInfoResult();
        result.setPageNo(pageInfo.getPageNum());
        result.setCurrentPageNum(pageInfo.getSize());
        result.setTotal(pageInfo.getTotal());
        result.setTotalPages(pageInfo.getPages());
        result.setList(pageInfo.getList());
        return result;
    }

    /**
     * 分页数据转换
     * 将mybatis的分页数据转为自定义分页数据
     * @param iPage
     * @return
     */
    public static PageInfoResult convert(IPage iPage) {
        PageInfoResult result = new PageInfoResult();
        result.setPageNo(new Long(iPage.getCurrent()).intValue());
        result.setCurrentPageNum(new Long(iPage.getSize()).intValue());
        result.setTotal(iPage.getTotal());
        result.setTotalPages(new Long(iPage.getPages()).intValue());
        result.setList(iPage.getRecords());
        return result;
    }
}

使用递归进行组装评论树,这样就OK了,结果如下:
在这里插入图片描述

{
  "msg": "操作成功",
  "code": 200,
  "data": {
    "pageNo": 1,
    "currentPageNum": 3,
    "total": 3,
    "totalPages": 1,
    "list": [
      {
        "commentId": 2,
        "userId": 12,
        "avatar": "",
        "nickName": "田七",
        "commentContent": "不错不错",
        "upvoteCount": 0,
        "whetherTop": 1,
        "createTime": "2021-06-18 14:41",
        "commentNodeTreeVos": [
          {
            "commentId": 4,
            "userId": 2,
            "avatar": "",
            "nickName": "张三",
            "commentContent": "啥不错?",
            "upvoteCount": 0,
            "whetherTop": 0,
            "createTime": "2021-06-18 14:42",
            "commentNodeTreeVos": [
              {
                "commentId": 5,
                "userId": 12,
                "avatar": "",
                "nickName": "田七",
                "commentContent": "这篇文章写的不错!",
                "upvoteCount": 0,
                "whetherTop": 0,
                "createTime": "2021-06-18 14:43",
                "commentNodeTreeVos": [
                  {
                    "commentId": 7,
                    "userId": 1,
                    "avatar": "http://xxx.oss-cn-shenzhen.aliyuncs.com/upload/xxx/20210127/4441d54f-1847-4d35-a58d-a2cafc159e74.gif",
                    "nickName": "谢哥哥",
                    "commentContent": "谢谢支持",
                    "upvoteCount": 0,
                    "whetherTop": 0,
                    "createTime": "2021-06-18 16:06",
                    "commentNodeTreeVos": null
                  },
                  {
                    "commentId": 6,
                    "userId": 4,
                    "avatar": "",
                    "nickName": "李四",
                    "commentContent": "是挺不错的",
                    "upvoteCount": 0,
                    "whetherTop": 0,
                    "createTime": "2021-06-18 14:44",
                    "commentNodeTreeVos": null
                  }
                ]
              }
            ]
          }
        ]
      },
      {
        "commentId": 3,
        "userId": 5,
        "avatar": "",
        "nickName": "王五",
        "commentContent": "博主厉害呀!!!",
        "upvoteCount": 0,
        "whetherTop": 0,
        "createTime": "2021-06-18 14:42",
        "commentNodeTreeVos": null
      },
      {
        "commentId": 1,
        "userId": 11,
        "avatar": "",
        "nickName": "赵六",
        "commentContent": "写的不错",
        "upvoteCount": 0,
        "whetherTop": 0,
        "createTime": "2021-06-18 14:40",
        "commentNodeTreeVos": null
      }
    ]
  }
}

写在最后

谢谢你的点击与阅读,如果文章对你有帮助的话,请动动您发财的小手点个小赞、收藏或者关注博主一下,谢谢!一心原创,为了后人乘凉。

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
本资源是一个基于Spring Boot和MySQL的母婴商城系统的完整源码,适用于JAVA毕业设计或项目实践。该系统采用了当下流行的微服务架构,以Spring Boot作为后端开发框架,MySQL作为数据库管理系统,实现了一个功能完善的母婴商城系统。主要功能包括:用户模块:注册、登录、修改个人信息、查询订单等;商品模块:商品分类、商品列表、商品详情、商品搜索等;购物车模块:添加商品、修改数量、删除商品等;订单模块:下单、支付、查看订单详情、订单状态跟踪等;评论模块:对已购买的商品进行评价;管理员模块:商品管理、订单管理、用户管理等。技术特点:采用Spring Boot作为后端开发框架,简化了开发流程,提高了开发效率;使用MyBatis作为持久层框架,实现与MySQL数据库的高效交互;使用Thymeleaf作为前端模板引擎,实现前后端分离,提高页面渲染性能;采用RESTful API设计风格,方便前后端数据交互;使用JWT(JSON Web Token)实现用户身份认证和授权;使用Redis实现购物车数据的缓存,提高系统性能;使用RabbitMQ实现订单的异步处理,提高系统吞吐量。通过本资源的学习,你可以掌握以下技能:熟悉Spring Boot框架的使用;熟悉MySQL数据库的基本操作;熟悉MyBatis框架的使用;熟悉前后端分离的开发模式;熟悉RESTful API设计风格;掌握JWT的使用方法;掌握Redis和RabbitMQ的基本应用。总之,本资源提供了一个功能完善、技术先进的母婴商城系统,可以帮助你快速完成JAVA毕业设计,提升你的项目实战能力。
动漫网站的设计和实现涉及到多个方面,包括前端设计、后端开发、数据库设计等。以下是一个基于Java的动漫网站的设计和实现流程: 1. 确定网站需求和功能:首先需要确定动漫网站的需求和功能,比如用户登录、注册、查看动漫列表、搜索、评论、收藏等。 2. 进行前端设计:根据网站需求和功能,设计网站的前端页面。可以使用HTML、CSS、JavaScript等技术进行页面设计,并且应该设计响应式布局,适应不同设备的屏幕大小。 3. 进行后端开发:使用Java技术进行后端开发,包括实现用户注册、登录、动漫列表、搜索、评论、收藏等功能。可以使用Spring框架进行开发,它提供了很多便捷的功能,比如ORM、AOP等。 4. 实现数据库设计设计并实现数据库,存储网站的数据。可以使用MySQL、Oracle等数据库管理系统进行开发,根据实际需求设计数据库表结构。 5. 进行测试和调试:完成网站开发后,进行测试和调试,确保网站能够正常运行,用户可以顺畅地使用。 6. 部署上线:将网站部署到服务器上,让用户可以通过互联网访问网站。 总之,设计和实现一个基于Java的动漫网站需要多方面的技术,需要在前端、后端和数据库方面都有扎实的基础。同时,也需要对网站的用户需求和功能有深入的理解,才能够开发出用户满意的网站。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

谢咯咯剥壳

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值