Java递归实现文章多级评论

记录

最近在模仿简书来自己写接口,简单的CRUD就不说了,直到碰到了文章的多级评论,发现怎么设计SQL都只能实现二级评论,就是在在实体类里面加上下一级评论的属性。

解决方案

多级评论其实就是一个评论下可以再被评论,那么找所有评论不就是找到最上级评论,然后遍历最上级的评论,找到每一个上级评论的下级评论,整个过程其实就是一个简单的递归。

实现

这是我的数据库表
在这里插入图片描述
comment_status是标记这个评论是不是最上级评论(0:是,1:不是),parent_id是该评论的上级评论的id。

这是DTO对象

/**
 * @Author: Ember
 * @Date: 2021/4/13 20:18
 * @Description: 评论
 */
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
public class CommentDto {
    /**
     * 主键
     */
    private Integer id;

    /**
     * 评论者
     */
    private Integer accountId;

    /**
     * 上级评论
     */
    private Integer parentId;

    /**
     * 文章
     */
    private Integer blogId;

    /**
     * 评论内容
     */
    private String content;

    /**
     * 下级评论
     */
    private List<CommentDto> sons;

    /**
     * 发生日期
     */
    private String date;
}

设计两条SQL,一条是找最上级评论的,一条是根据上级评论来找下级评论的

    <select id="getCommentByBlogId" resultType="CommentDto" parameterType="Integer">
        SELECT bc.`blog_id` as blogId,bc.`parent_id` as parentId,bc.`id`,
        bc.`account_id` as accountId,bc.`content` as content,bc.`create_time` as date
        FROM blog_comment bc
        WHERE bc.`blog_id` = #{blogId}
        AND bc.`comment_status` = 0;
    </select>

    <select id="getCommentByParentId" resultType="CommentDto" parameterType="Integer">
        SELECT bc.`blog_id` as blogId,bc.`id`,bc.`account_id` AS accountId,
        bc.`content` AS content,
        bc.`create_time` AS DATE,
        bc.`parent_id` AS parentId
        FROM blog_comment bc
        WHERE bc.`parent_id` = #{parentId} AND bc.`comment_status` != 0;
    </select>

Service层的递归实现

/**
 * @Author: Ember
 * @Date: 2021/4/13 20:37
 * @Description:
 */
@Service
public class CommentServiceImpl implements CommentService {

    private CommentMapper commentMapper;

    @Autowired
    public void setCommentMapper(CommentMapper commentMapper) {
        this.commentMapper = commentMapper;
    }

    @Override
    public List<CommentDto> getAllCommentByBlogId(Integer blogId) {
        List<CommentDto> commentVos = this.commentMapper.getCommentByBlogId(blogId);
        List<CommentDto> sons = getSons(commentVos);
        return sons;
    }

    private List<CommentDto> getSons(Integer parentId){
        return this.commentMapper.getCommentByParentId(parentId);
    }


    private List<CommentDto> getSons(List<CommentDto> parents){
        if(parents == null || parents.size() == 0){
            return null;
        }
        for (CommentDto parent : parents) {
            int parentId = parent.getId();
            List<CommentDto> sonCommentVos = getSons(parentId);
            //递归找子评论
            parent.setSons(getSons(sonCommentVos));
        }
        return parents;
    }

此时只要前端传回文章的唯一标识blogId即可,下面是Controller层的代码

    @GetMapping("/{blogId}")
    public BaseResult getBlogById(@PathVariable("blogId") Integer blogId){
        return DataResult.success(this.commentService.getAllCommentByBlogId(blogId));
    }

使用Postman测试的结果

{
    "code": "0",
    "msg": "success",
    "data": [
        {
            "id": 1,
            "accountId": 2,
            "parentId": 0,
            "blogId": 1,
            "content": "这是一级评论",
            "sons": [
                {
                    "id": 2,
                    "accountId": 2,
                    "parentId": 1,
                    "blogId": 1,
                    "content": "这是二级评论",
                    "sons": [
                        {
                            "id": 5,
                            "accountId": 2,
                            "parentId": 2,
                            "blogId": 1,
                            "content": "这是三级评论",
                            "sons": [
                                {
                                    "id": 6,
                                    "accountId": 2,
                                    "parentId": 5,
                                    "blogId": 1,
                                    "content": "这是四级评论",
                                    "sons": null,
                                    "date": "2021-04-14 16:15:21"
                                }
                            ],
                            "date": "2021-04-14 16:14:36"
                        }
                    ],
                    "date": "2021-04-14 15:58:21"
                },
                {
                    "id": 3,
                    "accountId": 2,
                    "parentId": 1,
                    "blogId": 1,
                    "content": "这是二级评论",
                    "sons": null,
                    "date": "2021-04-14 16:14:02"
                },
                {
                    "id": 4,
                    "accountId": 2,
                    "parentId": 1,
                    "blogId": 1,
                    "content": "这是二级评论",
                    "sons": null,
                    "date": "2021-04-14 16:14:12"
                }
            ],
            "date": "2021-04-14 15:51:48"
        }
    ]
}

反思

思考需求如何实现时,不要只想着依靠SQL一步完成,结合算法和数据结构往往可以解决很多难以解决的问题。

  • 1
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 23
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值