2

JPAでQueryDSLを使用しています。

エンティティのいくつかのプロパティをクエリしたいのですが、次のようになります。

QPost post = QPost.post;
JPAQuery q = new JPAQuery(em);
List<Object[]> rows = q.from(post).where(...).list(post.id, post.name);

それは正常に動作します。

投稿のコメントなど、リレーション プロパティをクエリする場合:

List<Set<Comment>> rows = q.from(post).where(...).list(post.comments);

それも結構です。

しかし、関係と単純なプロパティを一緒にクエリしたい場合、たとえば

List<Object[]> rows = q.from(post).where(...).list(post.id, post.name, post.comments);

その後、何かがうまくいかず、不適切な SQL 構文が生成されました。

その後、1 つの SQL ステートメントでそれらをまとめてクエリすることはできないことに気付きました。

QueryDSL がどうにかして関係を処理し、追加のクエリを生成して (休止状態が遅延関係で行うのと同じように)、結果をロードすることは可能ですか?

それとも、2 回クエリを実行してから、両方の結果リストをマージする必要がありますか?

PS私が実際に欲しいのは、コメントのIDを持つ各投稿です。各投稿のコメント ID を連結する関数の方が優れているのですが、この種の表現は可能ですか?

q.list(post.id, post.name, post.comments.all().id.join())

次のようなサブクエリSQLを生成します(select group_concat(c.id) from comments as c inner join post where c.id = post.id)

4

2 に答える 2

5

Querydsl JPAはJPQLの表現度に制限されているため、QuerydslJPAでは要求していることは不可能です。ただし、QuerydslSQLを使用して表現することもできます。それは可能であるはずです。また、エンティティを投影するのではなく、リテラルとコレクションを投影すると、問題なく機能する可能性があります。

または、コメントIDのみを読み込んだ状態で投稿を読み込んでから、ID、名前、コメントIDを別の場所に投影することもできます。これは、アクセサに注釈が付けられている場合に機能するはずです。

于 2011-09-13T07:18:19.050 に答える
3

最も簡単なのは、投稿をクエリし、コメントにfetchJoinを使用することですが、ユースケースには遅すぎると思います。

投稿やコメントに必要なプロパティを単純に予測し、結果を手作業でグループ化する必要があると思います(必要な場合)。例えば

QPost post=...;
QComment comment=..;

List<Tuple> rows = q.from(post)
// Or leftJoin if you want also posts without comments
.innerJoin(comment).on(comment.postId.eq(post.id))
.orderBy(post.id) // Could be used to optimize grouping
.list(new QTuple(post.id, post.name, comment.id));

Map<Long, PostWithComments> results=...;
for (Tuple row : rows) {
  PostWithComments res = results.get(row.get(post.id));
  if (res == null) { 
    res = new PostWithComments(row.get(post.id), row.get(post.name));
    results.put(res.getPostId(), res);
  }
  res.addCommentId(row.get(comment.id));
}

注:この種のクエリでは、制限やオフセットを使用できません。

別の方法として、1)コメントが常にレイジープロキシになるようにマッピングを調整して、(プロパティアクセスを使用して)実際のオブジェクトを初期化せずにComment.getId()を実行できるようにし、2)Postでバッチフェッチ*を使用することもできます。コレクションのフェッチを最適化するためのコメント。このようにして、投稿をクエリし、パフォーマンスにほとんど影響を与えることなく、コメントのIDにアクセスできます。ほとんどの場合、コメントが非常に太い場合を除いて、これらの怠惰なプロキシは必要ありません。この種のコードは、低レベルの行処理がなくても確かに見栄えがよく、クエリで制限とオフセットを使用することもできます。クエリログを監視して、すべてが意図したとおりに機能することを確認してください。

*)バッチフェッチはJPAで直接サポートされていませんが、Hibernateはマッピングを介してサポートし、Eclipselinkはクエリヒントを介してサポートします。

たぶんいつかQuerydslはこの種の結果グループ化後処理をすぐにサポートするでしょう...

于 2011-09-13T08:43:36.373 に答える