1

如果实体 A 与实体 B 具有双向一对一或零对一映射。

映射如下:

<class name="EntityA" table="TABLE_A" mutable="true" lazy="true">
    <id name="idA" type="long" column="pk_a" unsaved-value="null">
        <generator class="sequence">
            <param name="sequence">pk_a_seq</param>
        </generator>
    </id>
    <one-to-one name="propertyB" class="EntityB" property-ref="propertyA" constrained="true" outer-join="false"/>
</class>

<class name="EntityB" table="TABLE_B" mutable="true" lazy="true">
    <id name="idB" type="long" column="pk_b" unsaved-value="null">
        <generator class="sequence">
            <param name="sequence">pk_b_seq</param>
        </generator>
    </id>
    <many-to-one name="propertyA" class="EntityA" not-null="true" unique="true" lazy="proxy" column="fk_a"/>
</class>

当我为 EntityA 执行 hql 查询(或者更确切地说是命名的 hql 查询)时,hibernate 会急切地使用单独的 select 语句加载 EntityA#propertyB。

我的问题是,如果我的 hql 返回 1000 个 EntityA(都有各自的 EntityB),hibernate 将执行 n+1 个查询(第一个查询是 EntityA 返回 1000 个结果,而 n 个查询将来自 EntityA# propertyB 选择延迟加载)。

但是,我不需要那些 EntityA#propertyB,这就是为什么我想延迟加载它们(不让休眠使用单独的 sql 查询)。

那可能吗?如果是,我该怎么做?

谢谢,弗兰兹

4

2 回答 2

2

我已经解决了这个问题。

我所做的是创建将字段 EntityA#propertyB 转换为名称为 EntityA#propertyBs 的集合。但我保留了 EntityA#getPropertyB() 和 EntityA#setPropertyB(EntityB propertyB) 访问器方法。

这些访问器方法的方法体现在是这样的:

public EntityB getPropertyB() {
    return CollectionUtils.get(propertyBs, 0);
}

public void setPropertyBs(EntityB propertyB) {
    propertyBs= Collections.singleton(propertyB);
}

然后在我的映射中,我映射了集合 EntityA#propertyBs 并指定了对“字段”的访问。

<set name="scheduledAdInfos" lazy="true" fetch="subselect" access="field" cascade="none" inverse="true">
    <key column="pk_a"/>
    <one-to-many class="EntityB"/>
</set>

通过此设置,您现在可以创建从拥有的 POJO (EntityA) 到拥有的 POJO (EntityB) 的惰性映射,即使 TABLE_A 由 TABLE_B 拥有。

于 2009-07-23T10:25:03.943 回答
0

简短的回答:不,您不能这样做,至少在不更改数据库和映射的情况下不能这样做。您基本上必须反转一对一映射和外键关系才能以您想要的方式工作。


更长的答案:Hibernate 可以延迟加载关联。这样做的方法是注入一个保存引用对象 ID 的代理对象。

在您的情况下,映射使得外键列位于 TABLE_B 中,即您使用多对一映射的位置。所以如果你加载一个 B,hibernate 会在 fk_a 列中找到 FK 引用,并可以创建一个保存这个值的代理。当代理被访问时,相应的实体被加载。

如果选择了表 A 中的一条记录怎么办?Hibenate 将创建一个 A 对象,但为了能够填充属性 B,它必须查看 TABLE_B,以找到 fk_a=a.id 的对应行。Hibernate 没有其他方法可以在延迟加载时找出要加载的记录。

实际上,这对 Hibernate 来说是一个改进,因为它应该能够在延迟加载时对其他唯一键进行加载,但是当前的实现不允许这样做,也许你可以提出一个问题。

于 2009-06-10T17:59:41.500 回答