I am having trouble optimizing Hibernate queries to avoid performing joins or secondary selects.
When a Hibernate query is performed (criteria or hql), such as the following:
return getSession().createQuery(("from GiftCard as card where card.recipientNotificationRequested=1").list();
... and the where clause examines properties that do not require any joins with other tables... but Hibernate still performs a full join with other tables (or secondary selects depending on how I set the fetchMode).
The object in question (GiftCard) has a couple ManyToOne associations that I would prefer to be lazily loaded in this case (but not necessarily all cases). I want a solution that I can control what is lazily loaded when I perform the query.
Here's what the GiftCard Entity looks like:
@Entity
@Table(name = "giftCards")
public class GiftCard implements Serializable
{
private static final long serialVersionUID = 1L;
private String id_;
private User buyer_;
private boolean isRecipientNotificationRequested_;
@Id
public String getId()
{
return this.id_;
}
public void setId(String id)
{
this.id_ = id;
}
@ManyToOne
@JoinColumn(name = "buyerUserId")
@NotFound(action = NotFoundAction.IGNORE)
public User getBuyer()
{
return this.buyer_;
}
public void setBuyer(User buyer)
{
this.buyer_ = buyer;
}
@Column(name="isRecipientNotificationRequested", nullable=false, columnDefinition="tinyint")
public boolean isRecipientNotificationRequested()
{
return this.isRecipientNotificationRequested_;
}
public void setRecipientNotificationRequested(boolean isRecipientNotificationRequested)
{
this.isRecipientNotificationRequested_ = isRecipientNotificationRequested;
}
}
As said
If you have a mapping like this one
Any *ToOne relationship, such as @OneToOne and @ManyToOne, is, by default, FetchType.EAGER which means it will be always fetched. But, it could not be what you want. What you say as I can control what is lazily loaded can be translated as Fetching Strategy. POJO in Action book supports a pattern like this one (Notice method signature)
So based on your use case, you can create your own find...With...And... method. It will take care of fetching just what you want
But it has a problem: It does not support a generic method signature. For each @Entity repository, you have to define your custom find...With...And method. Because of that, i show you how i define a generic repository
But, sometimes, you do not want all of methods defined by generic Repository interface. Solution: create an AbstractRepository class which will implement a dummy repository. Spring Framework, for instance, heavily use this kind of pattern Interface >> AbstractInterface
So your GiftCardRepository can be re-written as (See extends instead of implements) and just overrides what you really want
Now we externalize our named query in a multiline - and readable and maintainable - xml file
So if you want to retrieve you GiftCard with Buyer, just call
And to retrieve our GiftCard without no relationship, just call
or use import static
And
I hope it can be useful to you!
In JPA the default fetch type for
ManyToOne
associations is eager (i.e. non-lazy) so could you try with:Then, in any JPA query the association can be eagerly fetched using
left join fetch
.