@LazyToOne 和 LazyToOneOption
旧版@LazyToOne 注释提供以下选项:
LazyToOneOption.FALSE
FALSE 选项等效于 JPA 的 FetchType.EAGER 注释,因此应避免使用它,因为它可能会导致严重的性能问题。
LazyToOneOption.PROXY
PROXY 选项等效于 JPA [FetchType.LAZY] 策略。但是,您应该更喜欢使用 JPA @OneToOne 或 @ManyToOne 关联的 fetch 属性。
LazyToOneOption.NO_PROXY
在父端使用@OneToOne 关联时,此策略很有用。
所以,假设您有以下 Post 和 PostDetails 实体:
如果Post映射了这个一对一表关系的父端:
@OneToOne(
mappedBy = "post",
fetch = FetchType.LAZY,
cascade = CascadeType.ALL
)
private PostDetails details;
即使关联使用FetchType.LAZY策略,我们可以看到如果我们要获取Post实体:
Post post = doInJPA(entityManager -> {
return entityManager.find(Post.class, 1L);
});
PostDetails 将被急切地获取:
SELECT p.id AS id1_0_0_,
p.title AS title2_0_0_
FROM post p
WHERE p.id = 1
SELECT pd.id AS id1_1_0_,
pd.created_by AS created_2_1_0_,
pd.created_on AS created_3_1_0_
FROM post_details pd
WHERE pd.id = 1
这是因为 Hibernate 不知道如何初始化 details 属性,因为它需要决定是使用 null 还是代理,而找出这一点的唯一方法是发出 SELECT 查询。
所以,要解决这个问题,我们需要做以下事情:
- 启用延迟获取字节码增强功能
- 使用
NO_PROXY 策略
要启用延迟加载字节码增强功能,我们可以使用这个 Hibernate Maven 插件:
<plugin>
<groupId>org.hibernate.orm.tooling</groupId>
<artifactId>hibernate-enhance-maven-plugin</artifactId>
<version>${hibernate.version}</version>
<executions>
<execution>
<configuration>
<enableLazyInitialization>true</enableLazyInitialization>
</configuration>
<goals>
<goal>enhance</goal>
</goals>
</execution>
</executions>
</plugin>
而且,我们还需要使用NO_PROXY 策略:
@OneToOne(
mappedBy = "post",
fetch = FetchType.LAZY,
cascade = CascadeType.ALL
)
@LazyToOne(LazyToOneOption.NO_PROXY)
private PostDetails details;
随着这一变化的到位,父端@OneToOne 关联将被延迟获取。