2

TL;DR

B コレクションにいくつかのプロパティしかない単一の A オブジェクトを取得するにはどうすればよいですか?

説明

私は、人々がすべての関係をEAGERとしてマッピングするという素晴らしいアイデアを持っていたレガシープロジェクトに取り組んでいます.

現在、パフォーマンスの問題が発生しています。

たとえば、B オブジェクトのリストを持つクラス A があります。そのリストは、休止状態のバッグとしてマップされ、遅延ロードされます (これまでのところ、非常に良好です)。問題は、B がおかしなアルファベット全体を熱心にロードすることです。

A.hbm.xml

<hibernate-mapping>
    <class="A" table="a" lazy="false">
        // properties
        <bag name="listOfBs" inverse="true">
            <key column="a_id" [...]>
            <one-to-many class="B" />
        </bag>
</hibernate-mapping>

B.hbm.xml

<hibernate-mapping>
    <class="B" table="b" lazy="false">
        <many-to-one name="a" class="A" column="a_id" />
        // lots of other many-to-one mappings

        // properties

        // lots of one-to-many properties
</hibernate-mapping>

したがって、必要な B のプロパティは 4 つだけですが、関連するすべてのオブジェクトがフェッチされます!

すべてを壊さずにこれを解決するために、hqlクエリを使用してコレクションのいくつかの列のみを選択しようとしています:

"select a, b.field1, b.field2, b.field3, b.field4
 from A a inner join B b where a.id = :id"

ただし、一意の結果が必要なため、次のクエリで例外が発生します。

4

3 に答える 3

1

上記のSQLを条件に変換した後、結果トランスフォーマーを設定できます。この場合、 AliasToBeanConstructorResultTransformer は機能します

最初に、基準からの結果列を含むクラスを作成します。

public class ResultPresenter{

private String a;
private String bField1;
private Integer bField2;
private String bField3;
private String bField4;

public ResultPresenter(String a, String bField1, Integer bField2, String bField3, String bField4){

this.a = a;
this.bField1 = bField1;
this.bField2 = bField2;
this.bField3 = bField3;
this.bField4 = bField4;
}
}

必要な列の投影を設定し、

ProjectionList projectionList = Projections.projectionList();
createProjectionList.add(projections.property(a));
createProjectionList.add(projections.property(b.field1));
createProjectionList.add(projections.property(b.field2));
createProjectionList.add(projections.property(b.field3));
createProjectionList.add(projections.property(b.field4));

AliasToBeanConstructorResultTransformer を条件に設定し、

java.lang.reflect.Constructor cons = ResultPresenter.class.getConstructor(Arrays.asList(new Class[]{String.class, String.class, Integer.class, String.class, String.class}));

criteria.setResultTransformer(new AliasToBeanConstructorResultTransformer(cons));
于 2013-09-14T01:00:45.380 に答える
0

2 つのクエリを使用して、必要なことを達成できました。1 つはオブジェクト A を取得するためのもので、もう 1 つは B オブジェクトのリストを作成するためのものです。2 つの基準と予測を使用して同じことができると思います。

まず、クラス B に新しいコンストラクターを作成しました。

class B {
    public B(String field1, String field2, String field3, String field4) {
        this.field1 = field1;
        this.field2 = field2;
        this.field3 = field3;
        this.field4 = field4;
    }
}

次に、クエリを作成しました。

public A fetch(Integer id) {
    // try-catch abstracted
    Query query = getSession.createQuery("from A a where a.id = :id");
    query.setParameter("id", id);

    A a = (A) query.uniqueResult();

    query = getSession().createQuery("select new B(b.field1, b.field2, b.field3, b.field4) from B where b.A.id = :id");
    query.setParameter("id", id);

    List<B> bs = query.list();

    a.setListOfBs(bs);

    return a;
}
于 2013-09-23T19:13:34.960 に答える
-1

hbmのsetタグにorder-byを記載してください。

<set name="subCompanies" lazy="false" order-by="lower(companyName)">
            ------------------------------
            ------------------------------          
</set>
于 2014-02-13T08:33:22.363 に答える