保存后懒惰忽略
Posted
技术标签:
【中文标题】保存后懒惰忽略【英文标题】:Lazy ignored after save 【发布时间】:2016-01-14 03:18:05 【问题描述】:我的控制器在 Spring Boot 上表现不同,我不知道为什么。我有这个模型:
@Entity
@Table(name = "comments")
@JsonInclude(JsonInclude.Include.NON_EMPTY)
public class Comment
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private boolean anonymous = false;
@Column(nullable = false, length = 150)
private String text;
@Temporal(TemporalType.TIMESTAMP)
@Column(nullable = false)
private Date date;
@ManyToOne(fetch = FetchType.EAGER)
private User user;
@ManyToOne(fetch = FetchType.LAZY)
private Post post;
// Getters and Setters
在我的控制器上我这样做:
@RequestMapping(value = "",
method = RequestMethod.POST,
produces = MediaType.APPLICATION_JSON_VALUE)
public Object createComment(Comment comment, HttpServletRequest request)
comment.setUser(userService.findByUsername(UserUtil.readUsernameFromUrlToken(request)));
Comment persistedComment = commentService.save(comment);
if(persistedComment != null)
if(persistedComment.isAnonymous())
persistedComment.setUser(null);
return persistedComment;
return new Error(Error.NOT_CREATED, "Comment not created!");
它返回带有 LAZY 注释的post
。但是当我在另一个控制器中获取时,它会返回预期的结果(没有懒惰的post
)
@RequestMapping(value = "/id/comments",
method = RequestMethod.GET,
produces = MediaType.APPLICATION_JSON_VALUE)
public Object findCommentsByPostId(@PathVariable("id") long postId)
List<Comment> comments = commentService.findByPostId(postId);
for(Comment comment : comments)
if(comment.isAnonymous())
comment.setUser(null);
return comments;
在这个请求映射中,它只返回user
,正如预期的那样。
我不知道为什么在第一个它返回懒惰post
,即使我这样做:
return commentService.findById(persistedComment.getId());
而不是
return persistedComment;
【问题讨论】:
如果调用第一个控制器,post 是否也包含在 JSON 中?如果是这样,那么帖子字段当然将填充该数据。由于持久化的对象随后存储在实体管理器中,因此在调用 findById 方法时会返回该对象。 感谢您的回答,是的,添加它是因为它来自请求postId
来填充关系。所以也可以理解post
也会返回。但是,为什么即使我使用return commentService.findById(persistedComment.getId());
,它也会返回post
,因为它只是使用持久对象的id
再次获取,就像其他请求一样,它一切正常?
AFAIK 如果您在实体管理器中有一个托管对象(您有,因为您已在该方法中保留了注释)并且您通过 id 检索该对象,那么来自实体管理器的对象将被使用,其中仍然包含帖子。
我明白了。我认为这就是原因。如果您可以向这些 cmets 发布答案,那么我可以接受。而且我认为在保存的情况下,我必须手动将我不想要的字段设置为空。感谢您的回复。
【参考方案1】:
如果您调用第一个控制器并且帖子也包含在 JSON 中,那么帖子字段当然会填充该数据。由于持久化对象随后作为托管对象存储在 entitymanager 中,因此当您调用 findById 方法时将返回此对象(实体管理器或 Hibernate 会话作为一级缓存)。
【讨论】:
【参考方案2】:在您的第一种情况下,一个新的评论对象被持久化并在同一个事务中获取。所以没有数据库调用来加载这个对象。评论对象 被持久化的对象按原样返回。Hibernate 将持久化对象保存在一级缓存中(休眠会话)。
【讨论】:
以上是关于保存后懒惰忽略的主要内容,如果未能解决你的问题,请参考以下文章
忽略 navigate() 调用:FragmentManager 已经保存了它的状态