0

だから私は以下のように2つの休止状態のポジョを持っています

class Owner{

Integer id;
String name;
Integer age;
String address;

/* 
  Many more fields here
*/

Set<Cat> cats;

}

class Cat{
Owner owner; //referenced from Owner.id
String color;
}

以下の基準を使用して所有者テーブルを照会しています -

Criteria criteria = session.createCriteria(Owner.class);
criteria.createAlias("cats", "cats");

ProjectionList projList = Projections.projectionList();
projList.add(Projections.property("id"), "id");
projList.add(Projections.property("name"), "name");
projList.add(Projections.property("cats"), "cats");

criteria.setProjection(projList);
criteria.setResultTransformer(Transformers.aliasToBean(Owner.class));
List<Owner> owners = (List<Owner>)criteria.list();

それぞれの猫が入力された所有者のリストが必要です。

プロジェクションを追加しない場合 ( select * と同等)、所有者ごとに猫が配置されます。ただし、所有者テーブルには他の多くのテーブルとの外部キー関係を持つ60を超える列があるため、select *は非常に高価になります。プロジェクションを使用して必要な列のみを選択し、クエリをより高速に実行したいと考えています。そして、プロジェクションやエイリアスを追加すると、所有者を取得しますが、猫は取得しません (各所有者の猫は null です)。

私はこれに対する解決策をたくさん検索し、基準でエイリアスとプロジェクションを作成するすべての方法を試しました。また、カスタム ResultTransformers を使用してみました。プロジェクションを使用している場合、それらのどれも機能しないようです。

他の誰かが同様の問題に直面しましたか? 何か案は?

4

1 に答える 1

1

質問はあまり明確ではありません。プロジェクションを追加しないと、所有者ごとに猫が配置されるとあなたは言います。しかし、射影リストでは射影フィールドとして猫を追加するので、基本的には結果に猫が必要ですよね? もしそうなら、予測を使用する唯一の理由は、所有者の年齢と住所を含めないことですか?

提案として、クエリから取得する SQL を考えてみてください。次のようなものが必要です。

select id, name from owner;

またはこのようなもの:

select o.id, o.namer, c.color from owner o join cat c on o.id = c.owner_id; 

最初に何を取得したいのか、次に Hibernate でそれを行う方法が重要だと思います。

編集: わかりました、私はあなたが今何を達成したいのか理解していると思います. しかし、あなたが望むようにそれを行うことができるとは思いません-猫も入力された所有者エンティティを直接抽出します。これは、プロジェクションを適用すると、デフォルトで結果が Owner エンティティのリストではなく、Object[] のリストになるためです。

たとえば、所有者 ID、所有者の名前、猫の色が必要だとします。予測は次のようになります。

projList.add(Projections.property("id"), "id");
projList.add(Projections.property("name"), "name");
projList.add(Projections.property("cats.color"), "catsColor");

生成されたSQLは、上記のcat joinのSQLと似ています。

次に、結果トランスフォーマーを適用できます。これはインターフェースからのメソッドです:

public Object transformTuple(Object[] tuple, String[] aliases);
public List transformList(List collection);

各行をオブジェクトにマップして返したい場合は、結果リストの各オブジェクトに対して最初のものが呼び出されますが、必要に応じて、リスト全体を処理して結果を組み合わせることができます。たとえば、猫の色のリストまたは catDtos のリストを持つ OwnerDto があり、結果をこのツリーのような構造に変換できるため、これが必要になる場合があります。結合のため、結果は次のようになることに注意してください (2 人の所有者がいて、それぞれに猫がいるとします):

tuple: [1, 'Owner1', 'white'] - aliases ['id', 'name', 'catsColor']
tuple: [1, 'Owner1', 'black'] - aliases ['id', 'name', 'catsColor']
tuple: [2, 'Owner2', 'yellow'] - aliases ['id', 'name', 'catsColor']
.. etc

そのため、この生のリストをより適切なものに結合する結果トランスフォーマーが必要です。

プロジェクションは、必要なデータのみを取得してパフォーマンスを向上させるのに非常に役立ちますが、返される結果はエンティティではないため、準備してそのまま使用する必要があります。DTO で射影されたデータを変換し、そのように使用する方がはるかに理にかなっています。これが、最初に射影を使用する理由であり、エンティティ全体を取得しないためですよね?

これで問題が解決することを願っています。これについてさらにアドバイスが必要な場合は、コメントを残してください。

于 2016-03-02T08:48:41.917 に答える