Hibernate 如何通过hql延迟加载一对一的合成

Hibernate 如何通过hql延迟加载一对一的合成,hibernate,hql,lazy-loading,one-to-one,many-to-one,Hibernate,Hql,Lazy Loading,One To One,Many To One,如果有一个实体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=

如果有一个实体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>

当我执行hql查询,或者更确切地说,为EntityA命名的hql查询时,hibernate急切地用一个单独的select语句加载EntityApropertyB

我的问题是,如果我的hql返回1000个EntityA,并且所有EntityB都有各自的EntityB,hibernate将执行n+1查询第一个查询将是EntityA返回1000个结果,而n个查询将来自EntityA属性选择延迟加载

但是,我不需要这些EntityApropertyB,这就是为什么我希望在不让hibernate使用单独的sql查询的情况下延迟加载它们

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

谢谢,
Franz

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

详细回答: Hibernate可以延迟加载关联。它这样做的方式是注入一个代理对象,该代理对象保存被引用对象的ID

在您的例子中,映射是这样的:外键列位于表_B中,即使用多对一映射的位置。因此,如果加载B,hibernate会在FK_a列中找到FK引用,并可以创建一个保存该值的代理。访问代理时,将加载相应的实体

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


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

我已经解决了这个问题

我所做的是创建并将字段EntityApropertyB转换为名为EntityApropertyB的集合。但我保留了EntityAgetPropertyB和EntityAsetPropertyBEntityB属性YB访问器方法

这些访问器方法的方法体现在如下所示:

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

public void setPropertyBs(EntityB propertyB) {
    propertyBs= Collections.singleton(propertyB);
}
然后在我的映射中,我映射了集合EntityApropertyBs并指定对“field”的访问

<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的惰性映射,即使表a由表B拥有。

我并不完全理解这个问题。如果对一组EntityA执行hql,则每当调用代理方法EntityA.getPropertyB时,将通过单独的查询加载相应的EntityApropertyB。这是正常的延迟加载行为。您到底希望该行为是什么?问题是因为我的query.list得到了n+1。根据我的调查,有两个原因:a。当我执行session.getNamedQueryQueryString..list时,Hibernate会返回所有匹配的EntityA及其EntityAgetPropertyB,这些EntityA都是经过初始化的。BEntityAgetPropertyB通过单独的select语句初始化。因此,通过一个query.list,我已经得到了n+1问题。如果我可以删除其中一个。或者b,那么我就可以解n+1了。更可取的是,我可以删除a。
<set name="scheduledAdInfos" lazy="true" fetch="subselect" access="field" cascade="none" inverse="true">
    <key column="pk_a"/>
    <one-to-many class="EntityB"/>
</set>