【问题标题】:Spring boot service not executing deleteBy from repositorySpring Boot 服务未从存储库执行 deleteBy
【发布时间】:2021-11-22 13:24:26
【问题描述】:

我正在做一个包含帖子和 cmets 的提要
帖子实体

public class Post extends AuditEntity {
    @Lob
    private String text;

    @Column
    private int totalCmnts = 0;

    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
    @JoinColumn(name = "post_id")
    private Set<Comment> comments;

    @ManyToOne
    @JoinColumn(name = "user_id", referencedColumnName = "id")
    private MEUser MEUser;

}

评论实体

public class Comment extends AuditEntity {
        @Lob
        private String text;
    
        @ManyToOne
        @JoinColumn(name = "user_id", referencedColumnName = "id")
        private MEUser MEUser;
    
}

并且我有一个服务来删除我获取帖子和评论的评论,我检查当前用户是否可以执行操作然后我删除评论并减少帖子实体中 cmets 的总数。

日志中的问题我可以看到选择操作和更新操作,但删除根本没有执行,仍然在服务类中获得带有@transactional 注释的 HTTP 200

我尝试了一个 SQL 查询,它运行良好

DELETE FROM `db-engine`.comment WHERE comment.id = 2

服务

@Override
public void deleteComment(Long commentID, Long postID, UserPrincipal currentUser) {
    Comment comment = commentsRepository.findById(commentID)
            .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
    Post post = postsRepository.findById(postID)
            .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
    if (comment.getMEUser().getId().equals(currentUser.getId())
            || currentUser.getAuthorities().contains(new SimpleGrantedAuthority(RoleName.ROLE_ADMIN.toString()))
            || currentUser.getAuthorities().contains(new SimpleGrantedAuthority(RoleName.ROLE_SUPER_ADMIN.toString()))) {

        commentsRepository.deleteById(comment.getId());
        post.setTotalCmnts(post.getTotalCmnts() - 1);
        System.out.println(comment.getId());
        System.out.println("hello");

    }
}

【问题讨论】:

  • 不是通过 CommentsRepository 显式删除评论,而是从 Post 实体的 comments 集合中删除评论。当 JPA 在事务结束时刷新时,它将从 comment 表中删除该行。

标签: java spring spring-boot jpql


【解决方案1】:

问题是您将post 实体更改为post.setTotalCmnts(post.getTotalCmnts() - 1);。这意味着 Hibernate 会注意到您的实体和数据库中的数据之间的差异并刷新它(从而更新数据库中的post)。 由于您在comments 上有@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true),这意味着Hibernate 会将持久操作级联到comments 实体。在此列表中,您仍然有要删除的 Comment,因此它会被再次创建(这里可能有一些 Hibernate 优化可以理解这一点,实际上并不会从数据库中删除它)。

您还需要从post comments 列表中删除要删除的Comment,如下所示:

commentsRepository.deleteById(comment.getId());
post.setTotalCmnts(post.getTotalCmnts() - 1);
post.setComments(post.getComments().remove(comment));
System.out.println(comment.getId());
System.out.println("hello");

另外,我会添加一个自定义的setComments() 方法,它会根据给定的参数实际更新totalCmnts,否则,您可能会得到不一致的数据。此外,getter 应该返回列表的副本而不是列表本身,否则,您可能会遇到一些非常讨厌的错误,因为您在其他地方更改了列表,并且此更改会在您不注意的情况下持续存在。

【讨论】:

    猜你喜欢
    • 2022-10-14
    • 2019-12-10
    • 2019-06-19
    • 2017-05-27
    • 2019-08-20
    • 2021-11-07
    • 1970-01-01
    • 1970-01-01
    • 2021-02-12
    相关资源
    最近更新 更多