Additional queries in JPA

半世苍凉 提交于 2019-12-02 07:38:41

问题


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?


回答1:


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




回答2:


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.



来源:https://stackoverflow.com/questions/20074881/additional-queries-in-jpa

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!