Reputation: 624
I have two classes InvitedPerson
and Flight
with a one to one relationship with each other. Here is how they are annotated.
public class InvitedTech{
...
@OneToOne(mappedBy="invitedTech", cascade = CascadeType.ALL, fetch=FetchType.LAZY)
public Flight flight;
@OneToOne(mappedBy="invitedTech", cascade = CascadeType.ALL, fetch=FetchType.LAZY)
public Hotel hotel;
...
}
public class Flight{
...
@OneToOne
@JoinColumn(name="invitedTechId", nullable=false)
public InvitedTech invitedTech;
...
}
As you can see Flight
is the owner of the relationship and InvitedTech
is the other side of this bidirectional relationship. InvitedTech also has a OneToOne
relationship with Hotel
Now, when I write a simple query to fetch all flights, it triggers three queries in total. 1st which gets me the results, but fires 2 additional queries.
List<Flight> flg = JPA.em().createQuery("SELECT flg from Flight flg").getResultList();
Why are query 2&3 being executed even though I have set FetchType=Lazy. I am not accessing Hotel Information. And Flight should not be queries again as the first query returns the data.
After some playing around when I remove mappedBy
attribute from both the annotations, those 2 addition queries don't get executed(i.e only 1st gets executed).
Why does the mappedBy
attribute cause additional queries to be executed even though FetchType=Lazy
. Is there a way to stop this?
Upvotes: 1
Views: 739
Reputation: 23246
I believe this is due to one of Hibernate's idiosyncrasies:
non-optional one-to-one relationships are eagerly loaded regardless of whether they are mapped as Lazy.
The reasoning behind this is that as the engine has to look in the association table anyway - to determine whether it should set the association as a proxy or as null - then it may as well load the associated entity anyway.
I have experienced this myself and as far as I know the only way round it is to mark the relationship with optional=false which tells Hibernate it can always set a proxy.
If the relationship is optional then the only other option seems to be byte code instrumentation.
See also:
https://community.jboss.org/wiki/SomeExplanationsOnLazyLoadingone-to-one
Making a OneToOne-relation lazy
Upvotes: 2
Reputation: 692281
You have not set the association from Flight to InvitedTech lazy. So it loads the InvitedTech associated with the flight.
Since it can't know from the InvitedTech if there exist a Hotel and a Flight associated with the InvitedTech, it can't decide if these fields should be null or should be proxies. So it's forced to execute additional queries to know if a hotel/flight exists for the InvitedTech.
Upvotes: 0