2009-06-08 64 views
1

如果有一個實體A與雙向一或零到一的映射與實體B.如何延遲加載經由HQL一對一的組合物

的映射如下:

<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查詢),休眠急切地加載EntityA#propertyB一個單獨的select語句。

我的問題是,如果我的hql返回1000個EntityA(都有自己的EntityB),hibernate會做n + 1個查詢(第一個查詢是EntityA返回1000個結果,而n個查詢會到來從EntityA#屬性B選擇延遲加載)。

但是,我不需要那些EntityA#屬性B的,這就是爲什麼我想懶惰加載它們(沒有休眠使用單獨的SQL查詢)。

這可能嗎?如果是這樣,我該怎麼做?

感謝, 弗朗茨

+0

我不完全瞭解問題。如果您爲一組EntityA執行hql,則只要您調用代理方法EntityA.getPropertyB(),就會通過單獨的查詢加載相應的EntityA#propertyB。這是正常的懶惰加載行爲。你想要什麼行爲? – 2009-06-08 14:20:00

回答

2

我修復了這個問題。

我所做的就是將字段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_A由表-B擁有。

0

簡短的回答:不,你不能做到這一點,至少在沒有改變數據庫的映射。您基本上必須將您想要的方式反轉一對一映射和外鍵關係才能工作。


較長的回答: Hibernate可以延遲加載關聯。這樣做的方式是通過注入一個代理對象來保存被引用對象的ID。

在你的情況下,映射是這樣的:外鍵列在TABLE_B中,也就是你使用多對一映射的地方。因此,如果加載B,hibernate會在fk_a列中找到FK引用,並且可以創建一個包含此值的代理。當代理被訪問時,相應的實體被加載。

如果選擇表A的記錄會怎麼樣? Hibenate將創建一個A對象,但爲了能夠填充屬性B,它將不得不查看TABLE_B,以找到fk_a = a.id所對應的行。 Hibernate沒有其他方法可以找出在延遲加載時加載哪條記錄。

實際上,這對Hibernate來說是一個改進,因爲它也應該能夠在延遲加載時對其他唯一鍵進行加載,但是當前的實現不允許這樣做,也許可以引發一個問題。