SpartanElite
SpartanElite

Reputation: 624

Additional queries in JPA

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();
  1. Query that gets all flights (This is the only one that I need)
  2. Query with a join between InvitedTech and Flight
  3. Query with a join between invitedTech and Hotel

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

Answers (2)

Alan Hay
Alan Hay

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

JB Nizet
JB Nizet

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

Related Questions