1

エンティティ B との双方向の 1 または 0 対 1 マッピングを持つエンティティ 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>

EntityA に対して hql クエリ (または名前付き hql クエリ) を実行すると、hibernate は別の select ステートメントで EntityA#propertyB を積極的に読み込みます。

それに関する私の問題は、私の hql が 1000 個の EntityA を返した場合 (すべてが独自の EntityB を持っている)、休止状態が n+1 クエリを実行することです (最初のクエリは 1000 の結果を返す EntityA 用であり、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>

この設定により、TABLE_AがTABLE_Bによって所有されている場合でも、所有しているPOJO(EntityA)から所有しているPOJO(EntityB)への遅延マッピングを作成できるようになりました。

于 2009-07-23T10:25:03.943 に答える
0

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


より長い答え: Hibernate は関連付けを遅延ロードできます。これを行う方法は、参照されるオブジェクトの ID を保持するプロキシ オブジェクトを注入することです。

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

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

実際、これは Hibernate の改善になります。遅延読み込み中に他の一意のキーを読み込むこともできるはずですが、現在の実装ではこれが許可されていないため、問題を提起できる可能性があります。

于 2009-06-10T17:59:41.500 に答える