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