Spring 引导服务未从存储库执行 deleteBy
Spring boot service not executing deleteBy from repository
我正在做一种带有 post 和评论
的提要
Post实体
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;
}
我有一个删除评论的服务,我在其中获取 post 和评论,我检查当前用户是否可以执行该操作,然后我删除评论并减少评论总数post实体。
日志中的问题我可以看到 select 操作和更新操作,但是根本没有执行删除操作,并且仍然在服务中使用 @transactional 注释获取 HTTP 200 class
我尝试了一个 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");
}
}
问题是您正在将 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 应该 return 列表的副本而不是列表本身,否则,您可能会遇到一些非常讨厌的错误,因为您在其他地方更改了列表并且此更改会在您没有注意到的情况下持续存在。
我正在做一种带有 post 和评论
的提要
Post实体
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;
}
我有一个删除评论的服务,我在其中获取 post 和评论,我检查当前用户是否可以执行该操作,然后我删除评论并减少评论总数post实体。
日志中的问题我可以看到 select 操作和更新操作,但是根本没有执行删除操作,并且仍然在服务中使用 @transactional 注释获取 HTTP 200 class
我尝试了一个 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");
}
}
问题是您正在将 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 应该 return 列表的副本而不是列表本身,否则,您可能会遇到一些非常讨厌的错误,因为您在其他地方更改了列表并且此更改会在您没有注意到的情况下持续存在。