2009-06-08 10 views
1

を介して次のようにエンティティとの双方向の一又はゼロ対1のマッピングB.どのように怠惰な負荷一対一組成HQL

マッピングとエンティティAがある場合:

<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> 

私は、エンティティAのためのHQLクエリ(またはむしろ、名前付きHQLクエリ)を行うと、熱心に別のselect文でエンティティA#propertyBをロード休止状態。

私のhqlがEntityAの1000個のEntityAを持ち、EntityBがn + 1個のクエリを実行している場合(EntityAが1000個の結果を返す最初のクエリ、n個のクエリが来る) EntityA#propertyBからlazy loadingを選択します)。

しかし、私はこれらのEntityA#propertyBを必要としません。なぜなら、(別のSQLクエリを使用して休止しないで)代わりにそれらを読み込みたいからです。

これは可能ですか?それがあれば、どうしたらいいですか?

おかげで、 フランツ

+0

私は問題を正確に理解していません。プロキシされたメソッドEntityA.getPropertyB()を呼び出すたびに、EntityAのセットに対してhqlを実行すると、対応するEntityA#propertyBが別のクエリを介してロードされます。これは通常の遅延ロードされた動作です。あなたは行動を正確に何にしたいですか? –

+0

問題は、query.list()でn + 1を取得しているためです。私がsession.getNamedQuery( "myQueryString")。 .list()を実行すると、Hibernateは一致するすべてのEntityAをEntityA#getPropertyBで返します。熱心に初期化されました。 b。)EntityA#getPropertyB()は、別のselect文を使用して初期化されます。 したがって、1つのquery.list()では、すでにn + 1の問題が発生しています。私が(a。)か(b。)のどちらかを取り除くことができれば、私はn + 1を解決することができます。好ましくは、私は(a。) –

答えて

2

この問題は修正されました。

私がしたことは、EntityA#propertyBフィールドをEntityA#propertyBsという名前のSetに変更することでした。しかし、私はEntityA#getPropertyB()とEntityA#setPropertyB(EntityBプロパティB)アクセサメソッドを保持していました。

これらのアクセサメソッドのメソッド本体は今、このようなものです:

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

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

はその後、私のマッピングで、私はセットエンティティA#propertyBsをマッピングし、「フィールド」へのアクセスを指定します。この設定で

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

、あなたは今TABLE_AがTABLE_Bによって所有されている場合でも所有POJO(EntityB)に所有するPOJO(エンティティA)から怠惰なマッピングを作成することができます。

0

短い答え:いいえ、あなたは、少なくともではないデータベースとのマッピングを変更することなく、それを行うことはできません。基本的には、1対1のマッピングと外部キーの関係を必要な方法で取り消す必要があります。


長い答え: 休止することができます遅延ロード団体。これを行う方法は、参照されるオブジェクトのIDを保持するプロキシオブジェクトを挿入することです。

マッピングでは、外部キー列がTABLE_Bにあり、つまり多対1マッピングを使用しています。したがって、Bをロードすると、hibernateはfk_a列でFK参照を見つけ、この値を保持するプロキシを作成できます。プロキシにアクセスすると、対応するエンティティがロードされます。

テーブルAのレコードを選択するとどうなりますか? HibenateはAオブジェクトを作成しますが、プロパティBを満たすには、TABLE_Bを調べてfk_a = a.idの対応する行を見つけなければなりません。 Hibernateが遅延ロード時にロードするレコードを見つける方法は他にありません。

実際には、これはHibernateの改善です。遅延ロード中に他のユニークキーのロードもできるはずですが、現在の実装ではこれを許可していない可能性があります。

関連する問題