Fetch Type LAZY 仍然会导致 Eager 加载 Hibernate Spring 数据

Posted

技术标签:

【中文标题】Fetch Type LAZY 仍然会导致 Eager 加载 Hibernate Spring 数据【英文标题】:Fetch Type LAZY still causes Eager loading Hibernate Spring data 【发布时间】:2016-07-16 20:58:20 【问题描述】:

我用 Spring 数据创建了一个简单的 Spring boot 项目。

我有一个与标签有一对多关系的 TagGroup 实体。

 @Entity
 @Table(name = "TAG_GROUP")
 public class TagGroup

  @OneToMany(fetch=FetchType.LAZY,mappedBy = "tagGroup")
  private Set<Tag> tagList;

 

标签实体如下

  @Entity
  @Table(name = "TAGS")
  public class Tag 

      @ManyToOne(optional = false,fetch=FetchType.LAZY)
       @JoinColumn(name = "TAG_GROUP_ID")
       private TagGroup tagGroup;

  

我正在使用 Spring 数据扩展 JPArepository 并使用它的 findAll 方法。

问题,Lazy fetch 不起作用但实际上它正在加载标签列表,而没有像 EAGER 一样显式调用 tagList...

谁能告诉我我在这里做错了什么?

【问题讨论】:

您能否显示您正在检索此对象并期待 LazyInitialization 异常的方法/类。 并不是我期待惰性初始化异常。只是行为本该懒惰时才急切。我正在使用标准 MVC 结构。 Spring 数据接口自动连接到由 Controller 调用的服务。此外,正如我所说,这是基本的 Spring 引导项目,仅此而已。 【参考方案1】:

这是因为属性spring.jpa.open-in-view=true

根据spring-boot-configuration Spring boot 应用程序使用spring.jpa.open-in-view=true

有了这个属性

注册 OpenEntityManagerInViewInterceptor。将 JPA EntityManager 绑定到线程,以完成请求的整个处理。

因此,在您的情况下,随后当您调用getTagList() 即检索tagList 时,它随后会触发另一个查询以获取tagList,因为EntityManager 仍处于打开状态。

您可能知道,如果已加载父项的 entityManager 仍处于打开状态,则永远不会抛出 LazyInitializationException

要覆盖它,您可以在application.properties/application.yml 中添加spring.jpa.open-in-view=false,然后您应该会看到LazyInitializationException

【讨论】:

Sorry Madhusudana , spring.jpa.open-in-view=true 是为当前的 Web 请求保持相同的 EntityManager 以避免我无论如何都没有得到的延迟初始化异常!所以,请忘记那部分。也许您误读了这个问题,我已经改写了我的问题。请重新阅读。 @DragonZoned 我想我明白了。因此,您 没有显式调用 tagList 仍然是 tagList 实体。这太有趣了。您能否发布调用 findAll 时触发的 sql 查询。 @DragonZoned 根据映射,它应该是惰性的。我怀疑,可能是 tagList 被隐式调用或toString()TagGroup。为了排除这种可能性,因为,我认为您必须从某个 service 类中调用 findAll() 方法,您可以在该行之后立即放置一个 System.out.println("Loaded Taggroup"),您正在调用 findAll() 方法。如果我们看到任何select 查询被触发以在上面的sysout 之后获取taglist,我们至少可以确定tagList 的加载不是EAGER 和稍后发生的一些隐式调用的bcos。 遇到了问题。问题是当我将列表作为控制器的响应发送时的序列化。模型 bean 在导致问题的序列化期间调用标签列表。要么我需要一种方法来避免在序列化时休眠调用 taglist,要么使用视图对象填充模型 bean 属性并将其发送到响应。 使用@JsonView来决定什么时候序列化,什么时候不序列化

以上是关于Fetch Type LAZY 仍然会导致 Eager 加载 Hibernate Spring 数据的主要内容,如果未能解决你的问题,请参考以下文章

JPA 懒加载实践 fetch = FetchType.LAZY

关联实体和非关联实体之间的连接,导致在 JPQL 中使用 Lazy fetch 生成非持久实体不断抛出 JpqlSyntaxException

Hibernate的fetch

学说中 fetch="EAGER" 和 fetch="LAZY" 有啥区别

Hibernate LAZY fetch [重复]

javascript 使用Fetch实现Lazy