小而美博客删除博客时报错 Cannot delete or update a parent row: a foreign key constraint fails (“blog .t b

文章讲述了作者在使用SpringBoot和JPARepository开发个人博客系统时遇到的问题,即删除博客时由于评论间的依赖关系引发的错误。作者详细分析了问题,涉及数据库表结构和递归代码实现,以确保在删除博客时能正确清理相关评论。
摘要由CSDN通过智能技术生成

前言:

        在网上跟着一个up主用SpringBoot+JPA Repository写了小而美个人博客系统,后面在测试时发现,删除某些博客时会报错1451 - Cannot delete or update a parent row: a foreign key constraint fails ("blog .t blog. tag~, CONSTRAINT
^FKcbuwvhv 1i26t8olpvqwwarv7p^ FOREIGN KEY (blogs_ id) REFERENCES 't blog^ (id))
花了一两天的时间才把这个问题解决....个人比较笨qnq

原因分析:

        从报错的字面意思来理解就是因为该博客和其他表存在依赖关系,分析自己的数据库,t_comment表依赖于t_blog表的id,所以在删除博客之前应该先把该博客对应的评论删掉。

但事情没这么简单,因为各评论之间有“回复”和”被回复“的依赖关系,由父评论和子评论构成,在删除父评论之前,应该先把子评论删除。

如下图,44的parent_comment_id=43,说明43(父评论)被44(子评论)回复过,所以他们之间存在依赖关系,应先删除44,在删除43;

但事情还要更复杂一些,当我删除44时,发现它还同时被45,46,47依赖,所以...需要使用到递归来查找子评论并删除。

代码实现:

BlogServiceImpl.java

  
   @Transactional
    @Modifying
    @Override
    public void deleteBlog(Long id) {
//        Sort sort = Sort.by(Sort.Direction.DESC, "createTime");
        //通过blog的id中找出博客下面的评论
        List<Comment> byBlogId = commentRepositoryl.findByBlogId(id);
        //递归查找并删除该评论的子评论,即如果该评论有子节点,就说明这条评论和其他评论还有依赖关系,必须先删除对应的子评论
        findParentsAndDelete(byBlogId);
        //批量删除漏网之鱼
        commentRepositoryl.deleteInBatch(byBlogId);
        //最后删除blog
        blogRepository.deleteById(id);
    }

@Transactional
    @Modifying
    public void findParentsAndDelete(List<Comment> comments) {
//        List<Comment> parentComment;
        //遍历parentComment_id=null的评论集合,并删除所有和他们有依赖关系的评论
        for (Comment com:comments) {
            //select * from t_comment c where com.gteId=c.parentComment_id
            Optional<Comment> curCom = commentRepositoryl.findById(com.getId());
            //判断是否为空
            if(curCom.isPresent()){
                List<Comment>  parentComment = commentRepositoryl.findCommentByIdAndParentId(com.getId());
                if(parentComment.isEmpty()){
                    //如果parentComment为空,则说明该评论和其他评论没有依赖关系,直接删除
                    commentRepositoryl.deleteById(com.getId());

                }else{
                    //否则递归查询并删除和该评论有依赖的评论
                    findParentsAndDelete(parentComment);
                }
            }
            }


    }

CommentRepository.java

public interface CommentRepository extends JpaRepository<Comment,Long> {
    List<Comment> findByBlogIdAndParentCommentNull(Long blogId, Sort sort);
    @Query("select c from Comment c where c.blog.id=?1")
    List<Comment> findByBlogId(Long id);
    @Query("select c from Comment c where c.nickname=?1 and c.email=?2")
    List<Comment> findByNicknameAndEmail(String nickname,String email);
    
    //找出parent_id=id的评论
    @Query("select c from Comment c where c.parentComment.id=?1")
    List<Comment> findCommentByIdAndParentId(Long id);
}

BlogController.java

   @GetMapping("/blogs/{id}/delete")
    public String delete(@PathVariable Long id,RedirectAttributes attributes){
        blogService.deleteBlog(id);
        attributes.addFlashAttribute("message","删除成功");
        return "redirect:/admin/blogs";
    }

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值