Reputation: 4746
I am currently using the Hibernate @LazyToOne
annotation.
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?
Upvotes: 3
Views: 13737
Reputation: 153950
@LazyToOne
and LazyToOneOption
The legacy @LazyToOne
annotation provides the following options:
FALSE
PROXY
NO_PROXY
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.
LazyToOneOption.PROXY
The PROXY
option is equivalent to the JPA [FetchType.LAZY
] strategy. However, you should prefer using the fetch
attribute of the JPA @OneToOne
or @ManyToOne
associations instead.
LazyToOneOption.NO_PROXY
This strategy is useful when using the @OneToOne
association on the parent side.
So, assuming you have the following Post
and PostDetails
entities:
If the Post
maps the parent-side of this one-to-one table relationship:
@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:
Post post = doInJPA(entityManager -> {
return entityManager.find(Post.class, 1L);
});
The PostDetails
is going to be fetched eagerly:
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.
So, to fix this issue, we need to things:
NO_PROXY
strategyTo enable lazy loading bytecode enhancement, we can use this Hibernate Maven plugin:
<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:
@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.
Upvotes: 4
Reputation: 3169
It should be
@OneToOne(fetch = FetchType.LAZY, optional=false)
Found on this forum: 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. Hence optional attributes are always fetched regardless.
Upvotes: 0
Reputation: 1
You can create a jpql
, like:
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.
Upvotes: 0