保存后懒惰忽略

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 已经保存了它的状态

Textarea 忽略输入但需要触发保存按钮

Matlab保存忽略大单元格数组

NHibernate - 外连接,不懒惰,忽略未找到 - 你如何在一个语句中构建对象?

在保存休眠实体时忽略瞬态模式

自定义 FieldSetMapper 中忽略的自动装配 JpaRepository 保存