JPA中与Hibernate的@LazyToOne注解等价的是什么?

3

我目前正在使用Hibernate的@LazyToOne注释。

由于我正在从Hibernate切换到JPA,我想知道在JPA中是否有@LazyToOne,或者是否有其他注释在JPA中提供相同的功能?


像这样的@ManyToOne(fetch = FetchType.LAZY)。 - Paris Tao
4个回答

4

@LazyToOneLazyToOneOption

传统的@LazyToOne注解提供以下选项:

  • FALSE
  • PROXY
  • NO_PROXY

LazyToOne annotation

LazyToOneOption.FALSE

FALSE选项相当于JPA的FetchType.EAGER注解,因此应避免使用它,因为它可能会导致严重的性能问题。

LazyToOneOption.PROXY

PROXY选项相当于JPA [FetchType.LAZY]策略。但是,您应该优先使用JPA @OneToOne@ManyToOne关联的fetch属性。

LazyToOneOption.NO_PROXY

当在父侧使用@OneToOne关联时,此策略很有用。

因此,假设您有以下PostPostDetails实体:

Post and PostDetails entities

如果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关联将会被延迟加载。


但根据文档,使用FALSE将会主动加载关联对象,而使用NO_PROXY将返回在请求引用时加载的真实对象。但是,急切加载不就意味着返回真实对象而不是代理吗?那么,这两者之间有什么区别呢? - Kawsar Ahmed

0

4
除非您还设置了 optional=true,否则此选项与 @LazyToOne 不同。可为空的一对一引用始终是急加载。 - ar31
1
你是不是想说 optional=false? - xtian

0
你可以创建一个 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();`

这可能解决你的问题。但是,你必须记得编写默认构造函数。


0

应该是这样的

@OneToOne(fetch = FetchType.LAZY, optional=false)

在这个论坛上发现:https://forum.hibernate.org/viewtopic.php?p=2388783 我猜原因是JPA唯一知道属性是否已经被获取的方法是检查它是否有值,但如果null是一个有效的值,那么就无法判断。因此,可选属性总是被获取。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接