一尘不染

如何通过HQL延迟加载一对一合成

hibernate

如果实体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,这就是为什么我想懒加载它们的原因(无需让hibernate使用单独的sql查询)。

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

谢谢弗朗兹


阅读 309

收藏
2020-06-20

共1个答案

一尘不染

我已经解决了这个问题。

我所做的就是创建将字段EntityA#propertyB转换为名称为EntityA#propertyBs的Set的方法。但是我保留了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_B由TABLE_B拥有也是如此。

2020-06-20