【问题标题】:Should relations only be LAZY or EAGER in hibernate?在休眠状态下,关系应该只是 LAZY 还是 EAGER?
【发布时间】:2019-01-21 15:47:54
【问题描述】:

我对 Hibernate fetch 选项有点困惑。我在我的项目中使用 Spring Boot 2、Spring Data 和 Hibernate。假设我有一个实体User。每个User 可能有很多Post,当然每个Post 可能有很多Comment 实体。我设计了SQL 数据库表,如下所示;

User
id (PK)
username
password

Post
id (PK)
title
content
user_id (FK)

Comment
id (PK)
content
post_id (FK)

因此,如果我需要列出特定用户的帖子,则无需获取 cmets。 LAZY fetch 当然会更好。但是,如果我需要返回特定的帖子做显示,我需要同时获取帖子及其 cmets。所以,EAGER fetch 应该被使用。

我应该如何在我的类中定义提取类型?我确信这些关系数据库有一种设计模式,但我想不通。所有教程都解释了 LAZY 和 EAGER 获取类型、优缺点,但是当我需要同时使用 LAZY 和 EAGER 时,我没有找到该怎么做。我试图定义 fetches LAZY 并使用Spring Data Repository 接口来简化数据库查询。对于 EAGER 获取,我尝试编写自定义数据库查询。但是,我无法查询嵌套连接(即查询特定用户的所有帖子及其 cmets)。我可以查询第一个用户,然后每个用户发布然后每个发布 cmets,但正如您所知,它不应该是这样。

这类关系数据的常见模式是什么? H

【问题讨论】:

  • 您无需编写查询,只需指定如何使用 @OneToMany(fetch=FetchType.LAZY) 获取数据即可。
  • 当我这样做时,如果我尝试访问 post.cmets,它会抛出一个 LazyInitializationException
  • 我认为你的 JPA 配置有问题

标签: java mysql hibernate spring-boot spring-data-jpa


【解决方案1】:

您应该使用@OneToManyFetchType.LAZY(无需设置为默认值)

public class Post {

    //other fields
    @OneToMany
    private List<Comment> comments;

    //getters and setters
    public List<Comment> getComments() {
        return comments;
    }

    public void setComments(List<Comment> comments) {
        this.comments = comments;
    }
}

此外,如果您尝试在事务范围之外访问 List,那么您将获得 LazyInitializationException,因为 hibernate 不会发出额外的查询来获取 FetchType.LAZY 集合的值。

要在事务范围之外解决此问题,您可以使用

Hibernate.initialize(post.getComments());

对于您希望加载 cmets 的帖子。但是,如果您尝试访问事务范围内的 cmets,则无需手动初始化,hibernate 将按需发出查询。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-10-24
    • 2020-04-07
    • 1970-01-01
    • 1970-01-01
    • 2012-12-30
    • 2011-05-10
    • 1970-01-01
    相关资源
    最近更新 更多