Hibernate @OneToOne即使使用@Fetch(FetchMode.JOIN)也会执行多个查询

时间:2014-02-18 11:30:47

标签: hibernate query-optimization fetch one-to-one

考虑与EmployeeAddress的关系。 EmployeeAddress之间存在一对一映射。以下是模特:

@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。

2 个答案:

答案 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语句。