【问题标题】:Hibernate @OneToOne executes multiple queries even with @Fetch(FetchMode.JOIN)即使使用 @Fetch(FetchMode.JOIN) Hibernate @OneToOne 也会执行多个查询
【发布时间】:2014-03-18 03:02:25
【问题描述】:

考虑与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 查询时,它会在内部生成两个查询。一个用于获取员工,另一个用于获取地址。

"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 只执行 1 个查询,并通过连接一次性获取 Employee 和 Address 数据。

知道为什么它会执行两个查询吗?如何让 Hibernate 使用 join 只执行一个查询?

我使用的是 Hibernate 3.3.0。

【问题讨论】:

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


    【解决方案1】:

    @OneToOne(fetch = FetchType.EAGER)@Fetch(FetchMode.JOIN) 与提到的 here 相同,您急于加载 Address,这意味着每当要求 Employee 获取 Address 时,也将获取 Address,根据 this doucment

    只有在访问关联时才会执行第二次选择。

    这意味着对Address 的查询只有在您访问它时才会执行,因此您应该使用@Fetch(FetchMode.SELECT)@OneToOne(fetch = FetchType.LAZY)

    更新:

    参考@Swathi 的帖子FetchMode 在使用Query 时总是被Hibernate 忽略,在这种情况下,它将为每个单独的实体、集合或连接负载使用选择。这意味着您必须创建自己的加入

    对于延迟加载,Hibernate 将忽略通过注解提供的FetchType,但如果映射是通过 XML 完成的,例如Employee.hbm.xml 类似这样的东西

     <one-to-one name="address" fetch="join" class="**PACKAGE**.Address"
            constrained="true" ></one-to-one>
    

    那么 Hibernate 将尊重延迟加载,并且仅在 lazy="false" 设置为 one-to-one 时执行第一个 select 语句,然后它将执行两个 select 语句。

    【讨论】:

    • 我想知道为什么即使我指定了 FetchMode.JOIN,它也执行两个单独的查询(一个加载员工,另一个加载地址)?虽然它可以使用单个连接查询来实现加载员工和地址。或者有没有一种方法可以指示 hibernate 使用连接查询来使用一个查询加载两个模型?
    【解决方案2】:

    使用显式 HQL 查询 "FROM Employee WHERE id = " + 1",Hibernate 将不遵守带注释的 Fetch 模式。您需要在 HQL 查询中指定 join 或在条件中指定 fetch 模式。

    当您使用 Query 接口 (Session.createQuery) 时,Hibernate 3.x 会忽略 Fetch Mode 注释,因此在这种情况下,您必须将 INNER JOIN FETCH 子句添加到查询的 FROM 部分。

    【讨论】:

    • 感谢您的解释。使用 INNER JOIN FETCH 会导致执行单个查询。
    • 如果我使用 From Employee 查询,我应该在哪里写 INNER JOIN FETCH
    • 我遇到了@SanketMeghani 报告的同样问题。我想知道为什么 Hibernate 在这种情况下不尊重注释。这有什么合理的解释吗?
    猜你喜欢
    • 2019-12-30
    • 2012-04-15
    • 2015-03-12
    • 1970-01-01
    • 1970-01-01
    • 2014-03-27
    • 1970-01-01
    • 2019-12-09
    • 1970-01-01
    相关资源
    最近更新 更多