简体   繁体   English

什么是 Hibernate @LazyToOne 注释的 JPA 等价物?

[英]What's the JPA equivalent of the Hibernate @LazyToOne annotation?

I am currently using the Hibernate @LazyToOne annotation.我目前正在使用 Hibernate @LazyToOne注释。

Since I'm switching from Hibernate to JPA, I'd like to know whether @LazyToOne is available in JPA, or is there any other annotation that provides the same functionality in JPA?由于我正在从 Hibernate 切换到 JPA,我想知道@LazyToOne在 JPA 中是否可用,或者是否有任何其他注释在 JPA 中提供相同的功能?

@LazyToOne and LazyToOneOption @LazyToOneLazyToOneOption

The legacy @LazyToOne annotation provides the following options:遗留的@LazyToOne注释提供以下选项:

  • FALSE
  • PROXY
  • NO_PROXY

LazyToOne 注释

LazyToOneOption.FALSE

The FALSE option is equivalent to the JPA FetchType.EAGER annotation, so it should be avoided as it can cause serious performance issues. FALSE选项等效于 JPA FetchType.EAGER注释,因此应避免使用,因为它会导致严重的性能问题。

LazyToOneOption.PROXY

The PROXY option is equivalent to the JPA [ FetchType.LAZY ] strategy. PROXY选项等效于 JPA [ FetchType.LAZY ] 策略。 However, you should prefer using the fetch attribute of the JPA @OneToOne or @ManyToOne associations instead.但是,您应该更喜欢使用 JPA @OneToOne@ManyToOne关联的fetch属性。

LazyToOneOption.NO_PROXY

This strategy is useful when using the @OneToOne association on the parent side.在父端使用@OneToOne关联时,此策略很有用。

So, assuming you have the following Post and PostDetails entities:因此,假设您有以下PostPostDetails实体:

Post 和 PostDetails 实体

If the Post maps the parent-side of this one-to-one table relationship:如果Post映射了这个一对一表关系的父端:

@OneToOne(
    mappedBy = "post",
    fetch = FetchType.LAZY,
    cascade = CascadeType.ALL
)
private PostDetails details;

Even if the association uses the FetchType.LAZY strategy, we can see that if we want to fetch the Post entity:即使关联使用了FetchType.LAZY策略,我们也可以看到,如果我们要获取Post实体:

Post post = doInJPA(entityManager -> {
    return entityManager.find(Post.class, 1L);
});

The PostDetails is going to be fetched eagerly: 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

This is because Hibernate doesn't know how to initialize the details property since it needs to decide whether to use null or a Proxy, and the only way to find that out is to issue a SELECT query.这是因为 Hibernate 不知道如何初始化details属性,因为它需要决定是使用null还是 Proxy,而找出这一点的唯一方法是发出 SELECT 查询。

So, to fix this issue, we need to things:因此,要解决此问题,我们需要:

  • enable lazy fetching bytecode enhancement启用延迟获取字节码增强
  • use the NO_PROXY strategy使用NO_PROXY策略

To enable lazy loading bytecode enhancement, we can use this Hibernate Maven plugin:要启用延迟加载字节码增强,我们可以使用这个 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>

And, we also need to use the NO_PROXY strategy:而且,我们还需要使用NO_PROXY策略:

@OneToOne(
    mappedBy = "post",
    fetch = FetchType.LAZY,
    cascade = CascadeType.ALL
)
@LazyToOne(LazyToOneOption.NO_PROXY)
private PostDetails details;

With this change in place, the parent-side @OneToOne association is going to be fetched lazily.有了这个更改,父端@OneToOne关联将被延迟获取。

You can use:您可以使用:

@OneToOne(fetch = FetchType.LAZY)

More details in this question: Making a OneToOne-relation lazy这个问题的更多细节: 使一对一关系变得懒惰

You can create a jpql , like:您可以创建一个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();`

It may solve your problem.它可能会解决您的问题。 But, you have to remember to write the default constructor.但是,您必须记住编写默认构造函数。

It should be它应该是

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

Found on this forum: https://forum.hibernate.org/viewtopic.php?p=2388783在这个论坛上找到: https : //forum.hibernate.org/viewtopic.php?p=2388783

The reason, I guess, is that the only way for JPA to know if an attribute has already been fetched is to check it has a value, but if null is a valid value then there's no way to tell.我猜,原因是 JPA 知道一个属性是否已经被获取的唯一方法是检查它是否有一个值,但如果 null 是一个有效值,那么就没有办法判断了。 Hence optional attributes are always fetched regardless.因此,无论如何总是获取可选属性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM