考虑与Employee
和Address
的关系。 Employee
和Address
之间存在一对一映射。以下是模特:
@Entity
@Table(name = "Address")
public class Address
{
@Id
@GeneratedValue
@Column(name = "addressId")
private int addressId;
@Column(name = "city")
private String city;
.
.
}
@Entity
@Table(name = "Employee")
public class Employee
{
@Id
@Column(name = "employeeId")
private int employeeId;
@Column(name = "name")
private String name;
@OneToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "addressId")
@Fetch(FetchMode.JOIN)
private Address address;
.
.
}
现在,当我执行以下HQL查询时,它会在内部生成两个查询。一个用于获取Employee,另一个用于获取地址。
"FROM Employee WHERE id = " + 1
Hibernate生成的SQL查询
Hibernate: select employee0_.employeeId as employeeId0_, employee0_.addressId as addressId0_, employee0_.name as name0_ from Employee employee0_ where employee0_.employeeId=1
Hibernate: select address0_.addressId as addressId1_0_, address0_.city as city1_0_ from Address address0_ where address0_.addressId=?
当我使用@Fetch(FetchMode.JOIN)
时,我希望Hibernate只使用连接执行一个查询,一次性获取Employee和Address数据。
知道它为什么执行两个查询,如何让Hibernate只使用join执行一个查询?
我正在使用Hibernate 3.3.0。
答案 0 :(得分:7)
使用显式HQL查询“FROM Employee WHERE id =”+ 1“,Hibernate将不会遵循带注释的获取模式。您需要在HQL查询中指定连接或在条件中指定获取模式。
当您使用Query接口(Session.createQuery)时,Hibernate 3.x会忽略获取模式注释,因此在这种情况下,您必须将INNER JOIN FETCH子句添加到查询的FROM部分。
答案 1 :(得分:0)
@OneToOne(fetch = FetchType.EAGER)
和@Fetch(FetchMode.JOIN)
与提及的here相同this doucment,这意味着每当Address
要求获取Employee
时也可以根据Query
只有在您访问关联时才会执行第二次选择。
这意味着Address
的查询只有在您访问时才会执行,因此您应该使用Address
和@Fetch(FetchMode.SELECT)
。
更新:
来自@ Swathi的帖子@OneToOne(fetch = FetchType.LAZY)
的引用在使用{{3}}时总是被Hibernate忽略,在这种情况下它将对每个单独的实体,集合或连接加载使用select。这意味着您必须创建加入自己的
对于延迟加载,Hibernate将忽略通过注释提供的FetchMode
,但是如果映射是通过XML完成的,例如。FetchType
,则有这样的事情
Employee.hbm.xml
然后Hibernate将尊重延迟加载,并且只有在 <one-to-one name="address" fetch="join" class="**PACKAGE**.Address"
constrained="true" ></one-to-one>
上设置lazy="false"
时才执行第一个select语句,然后它将执行两个select语句。