Search code examples
javasqlhibernatejpajpql

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?


Solution

  • 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