Spring Boot中双向一对多关系上的LazyInitializationException异常
以下Spring引导服务方法在尝试向Spring Boot中双向一对多关系上的LazyInitializationException异常,spring,hibernate,spring-data-jpa,open-session-in-view,Spring,Hibernate,Spring Data Jpa,Open Session In View,以下Spring引导服务方法在尝试向Post.addComment(Comment)中的Post添加Comment时抛出Hibernate的LazyInitializationException: 实体映射如下所示: import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; import javax.persistence.CascadeType; import javax.persis
Post.addComment(Comment)
中的Post
添加Comment
时抛出Hibernate的LazyInitializationException
:
实体映射如下所示:
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
@Entity
public class Post {
@Id
@GeneratedValue
private Long id;
private String title;
@Column(length = 4096)
private String content;
private LocalDateTime creationDate;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public LocalDateTime getCreationDate() {
return creationDate;
}
public void setCreationDate(LocalDateTime creationDate) {
this.creationDate = creationDate;
}
public Long getId() {
return id;
}
@OneToMany(
mappedBy = "post",
cascade = CascadeType.ALL,
orphanRemoval = true
)
private List<Comment> comments = new ArrayList<>();
public void addComment(Comment comment) {
comments.add(comment);
comment.setPost(this);
}
public List<Comment>getComments() {
return this.comments;
}
}
Comment
的post引用中的ManyToOne
获取类型的EAGER
或LAZY
,似乎没有什么区别
我做错了什么?如何解决这个错误
根据@mckszcz建议的更改,现在在尝试从帖子中获取评论时,同一服务上的以下方法会引发一些反射异常:
/**
* Returns a list of all comments for a blog post with passed id.
*
* @param postId id of the post
* @return list of comments sorted by creation date descending - most recent first
*/
public List<CommentDto> getCommentsForPost(Long postId) {
List<Comment> comments = postRepository.getOne(postId).getComments();
List<CommentDto> result = new ArrayList<>();
comments.forEach(comment -> {
result.add(new CommentDto(comment.getId(), comment.getComment(), comment.getAuthor(), comment.getCreationDate()));
});
return result;
}
/**
*返回已传递id的博客文章的所有评论的列表。
*
*@param postId该帖子的id
*@返回按创建日期降序排序的注释列表-最近的第一个
*/
公共列表getCommentsForPost(长帖子){
List comments=postRepository.getOne(postId.getComments();
列表结果=新建ArrayList();
评论。forEach(评论->{
添加(newcommentdto(comment.getId(),comment.getComment(),comment.getAuthor(),comment.getCreationDate());
});
返回结果;
}
如果要返回方法的javadoc中描述的属于帖子的所有评论列表,需要将其更改为什么?由于拥有方是这里的评论,您应该将
addComment
方法更改为:
public Long addComment(NewCommentDto newCommentDto) {
try {
Post post = postRepository.findById(newCommentDto.getPostId()).get();
Comment comment = new Comment();
comment.setComment(newCommentDto.getContent());
comment.setPost(post);
comment = commentRepository.save(comment);
return comment.getId();
} catch (Exception e) {
throw new IllegalArgumentException("There's no posts for given ID.");
}
}
因为拥有方在这里是Comment,所以您应该将
addComment
方法更改为:
public Long addComment(NewCommentDto newCommentDto) {
try {
Post post = postRepository.findById(newCommentDto.getPostId()).get();
Comment comment = new Comment();
comment.setComment(newCommentDto.getContent());
comment.setPost(post);
comment = commentRepository.save(comment);
return comment.getId();
} catch (Exception e) {
throw new IllegalArgumentException("There's no posts for given ID.");
}
}
结果表明,除了在
addComment
方法中重新排列代码以消除LazyInitializationException
(如@mckszcz所指出的,由JPA由于错误的拥有方
属性而抛出)之外:
为了解决服务的getCommentsForPost(Long postId)
方法中的反射InvocationTargetException
,还需要在CommentRepository
中引入一个额外的查找方法(允许通过包含父项的ID搜索多个子项):
@Repository
public interface CommentRepository extends JpaRepository<Comment, Long> {
List<Comment> findByPostId(Long postId);
}
@存储库
公共接口CommentRepository扩展了JpaRepository{
列表findByPostId(长postId);
}
然后在错误的方法中引入该存储库周围的相应更改:
/**
* Returns a list of all comments for a blog post with passed id.
*
* @param postId id of the post
* @return list of comments sorted by creation date descending - most recent first
*/
public List<CommentDto> getCommentsForPost(Long postId) {
List<Comment> commentsForPost = commentRepository.findByPostId(postId);
//List<Comment> comments = postRepository.getOne(postId).getComments();
List<CommentDto> result = new ArrayList<>();
commentsForPost.forEach(comment -> {
result.add(new CommentDto(comment.getId(), comment.getComment(), comment.getAuthor(), comment.getCreationDate()));
});
return result;
}
/**
*返回已传递id的博客文章的所有评论的列表。
*
*@param postId该帖子的id
*@返回按创建日期降序排序的注释列表-最近的第一个
*/
公共列表getCommentsForPost(长帖子){
List commentsForPost=commentRepository.findByPostId(postId);
//List comments=postRepository.getOne(postId.getComments();
列表结果=新建ArrayList();
commentsForPost.forEach(注释->{
添加(newcommentdto(comment.getId(),comment.getComment(),comment.getAuthor(),comment.getCreationDate());
});
返回结果;
}
这两项措施似乎解决了问题。结果表明,除了在
addComment
方法中重新排列代码,以消除懒散初始化异常
(正如@mckszcz所指出的,JPA由于错误的拥有方
属性而抛出):
为了解决服务的getCommentsForPost(Long postId)
方法中的反射InvocationTargetException
,还需要在CommentRepository
中引入一个额外的查找方法(允许通过包含父项的ID搜索多个子项):
@Repository
public interface CommentRepository extends JpaRepository<Comment, Long> {
List<Comment> findByPostId(Long postId);
}
@存储库
公共接口CommentRepository扩展了JpaRepository{
列表findByPostId(长postId);
}
然后在错误的方法中引入该存储库周围的相应更改:
/**
* Returns a list of all comments for a blog post with passed id.
*
* @param postId id of the post
* @return list of comments sorted by creation date descending - most recent first
*/
public List<CommentDto> getCommentsForPost(Long postId) {
List<Comment> commentsForPost = commentRepository.findByPostId(postId);
//List<Comment> comments = postRepository.getOne(postId).getComments();
List<CommentDto> result = new ArrayList<>();
commentsForPost.forEach(comment -> {
result.add(new CommentDto(comment.getId(), comment.getComment(), comment.getAuthor(), comment.getCreationDate()));
});
return result;
}
/**
*返回已传递id的博客文章的所有评论的列表。
*
*@param postId该帖子的id
*@返回按创建日期降序排序的注释列表-最近的第一个
*/
公共列表getCommentsForPost(长帖子){
List commentsForPost=commentRepository.findByPostId(postId);
//List comments=postRepository.getOne(postId.getComments();
列表结果=新建ArrayList();
commentsForPost.forEach(注释->{
添加(newcommentdto(comment.getId(),comment.getComment(),comment.getAuthor(),comment.getCreationDate());
});
返回结果;
}
这两项措施似乎解决了问题。你能解释一下
拥有方的含义吗?
请参考这篇文章:因为人们已经比我解释得更好了would@mckzcz:它似乎正在破坏其他反射调用,请看添加的代码。你能解释一下拥有方的含义吗?请参考这篇文章:因为人们已经比我解释得更好了would@mckzcz:它似乎正在破坏其他反射调用,请查看添加的代码。