我有两个班级InvitedPerson
和Flight
,彼此之间有一对一的关系。以下是它们的注释方式。
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;
...
}
正如您所看到的,Flight
是关系的所有者,而InvitedTech
是此双向关系的另一方。 InvitedTech与OneToOne
的关系也Hotel
现在,当我编写一个简单的查询来获取所有航班时,它总共会触发三个查询。第一个让我得到结果,但又引发了2个额外的查询。
List<Flight> flg = JPA.em().createQuery("SELECT flg from Flight flg").getResultList();
为什么即使我设置了FetchType = Lazy,也会执行查询2和3。我没有访问酒店信息。并且当第一个查询返回数据时,Flight不应再次成为查询。
当我从两个注释中删除mappedBy
属性时,一些玩游戏后,这两个附加查询不会被执行(即只执行第一次)。
为什么mappedBy
属性会导致执行其他查询,即使FetchType=Lazy
也是如此。有办法阻止这个吗?
答案 0 :(得分:2)
我认为这是由于Hibernate的特性之一:
无论是否将它们映射为Lazy,都会急切地加载非可选的一对一关系。
这背后的原因是,因为引擎必须查看关联表 - 确定它是应该将关联设置为代理还是作为null - 然后它也可以加载关联的实体。
我自己也经历过这一点,据我所知,唯一的方法是使用optional = false标记关系,告诉Hibernate它总能设置代理。
如果关系是可选的,那么唯一的其他选项似乎是字节码检测。
另见:
https://community.jboss.org/wiki/SomeExplanationsOnLazyLoadingone-to-one
答案 1 :(得分:0)
您尚未设置从Flight到InvitedTech lazy的关联。因此它加载与航班相关联的InvitedTech。
由于无法从InvitedTech知道是否存在与InvitedTech相关联的酒店和航班,因此无法确定这些字段是否应为空或应为代理。因此,它被迫执行其他查询以了解InvitedTech是否存在酒店/航班。