Hibernate @LazyToOne 注释的 JPA 等价物是啥?
Posted
技术标签:
【中文标题】Hibernate @LazyToOne 注释的 JPA 等价物是啥?【英文标题】:What's the JPA equivalent of the Hibernate @LazyToOne annotation?Hibernate @LazyToOne 注释的 JPA 等价物是什么? 【发布时间】:2013-05-06 04:00:55 【问题描述】:我目前正在使用 Hibernate @LazyToOne
注释。
由于我从 Hibernate 切换到 JPA,我想知道 @LazyToOne
在 JPA 中是否可用,或者是否有任何其他注释在 JPA 中提供相同的功能?
【问题讨论】:
@ManyToOne(fetch = FetchType.LAZY) 像这样。 【参考方案1】:
@LazyToOne
和 LazyToOneOption
旧版@LazyToOne
注释提供以下选项:
FALSE
PROXY
NO_PROXY
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
关联将被延迟获取。
【讨论】:
【参考方案2】:你可以使用:
@OneToOne(fetch = FetchType.LAZY)
这个问题的更多细节: Making a OneToOne-relation lazy
【讨论】:
这和@LazyToOne
不一样,除非你还设置了optional=true
,可为空的一对一引用总是急切的
你的意思是 optional=false?【参考方案3】:
你可以创建一个jpql
,比如:
User user = em.createQuery("SELECT NEW com.model.User(u.id, u.name, u.password)
FROM User u WHERE u.id = :id", User.class)
.setParameter("id", 1L)
.gerSingleResult();`
它可能会解决您的问题。但是,您必须记住编写默认构造函数。
【讨论】:
【参考方案4】:应该是
@OneToOne(fetch = FetchType.LAZY, optional=false)
在这个论坛上找到:https://forum.hibernate.org/viewtopic.php?p=2388783
我想,原因是 JPA 知道一个属性是否已经被获取的唯一方法是检查它是否有一个值,但如果 null 是一个有效值,那么就没有办法知道了。因此,无论如何总是会获取可选属性。
【讨论】:
以上是关于Hibernate @LazyToOne 注释的 JPA 等价物是啥?的主要内容,如果未能解决你的问题,请参考以下文章