5

「Players」と「Items」の2つのテーブルがあります。プレイヤーはアイテムのリストを持っています。ページネーションを使用して、プレーヤーとそのすべてのアイテムを取得したいと思います。アイテムの数に関係なく、プレーヤーに基づいてページ付けしたいと思います。

だから私はこのようなことをします:

Criteria c = session.createCriteria(Players.class).setFetchMode("items", FetchMode.JOIN);
c.addOrder(Order.asc("playerID"));
c.setFirstResult(0);
c.setMaxResults(25);
List<Player> players = c.list();

これで最初の25人のプレーヤーが得られますか、それとも最初の25個のアイテム(プレーヤーごとにグループ化されたもの)が得られますか?この動作がJPAクエリの場合のように未定義なのか、それとも確実な答えがあるのだろうかと思います。

とにかく、最初の25人のプレーヤーまたは最初の25人のプレーヤーとアイテムの組み合わせ(プレーヤーID、次にアイテムIDの順に)を取得する基準クエリとは何ですか?

4

2 に答える 2

11

Hibernateの「AdvancedProblems」FAQから:

http://community.jboss.org/wiki/HibernateFAQ-AdvancedProblems

setFirstResult(5)やsetMaxResults(10)などの結果セットの行ベースの「制限」操作がこれらの種類の熱心なフェッチクエリで機能しない理由も明らかです。結果セットを特定の行数に制限すると、データがランダムに切り取られます。ある日、Hibernateは、setFirstResult()またはsetMaxResults()を呼び出す場合、結合を使用するのではなく、2番目のSQLSELECTを使用する必要があることを知っているほど賢いかもしれません。試してみてください。Hibernateのバージョンはすでに十分にスマートである可能性があります。そうでない場合は、2つのクエリを記述します。1つは制限するためのもので、もう1つは熱心なフェッチのためのものです。

つまり、Hibernateはこれをサポートしていません。あなたが賢く、Hibernateがどのように実装されているかを知っていれば、setFirstResultとsetMaxResultsがすべての場合にページネーションのようにリモートで何もしないことは明らかだったはずです。それは文書化する必要がないほど明白でした。

于 2011-06-17T22:33:54.900 に答える
6

確かに、100%ではありませんが、次のようになります。

プレーヤーとアイテムを結合し、playerIDで並べ替えて、最初の25件の結果をすべて1つのSQLクエリで取得します。このデータから、プレーヤーとアイテムが作成され、合計25個のアイテムを持つ任意の数のプレーヤー(25以下)になります。最後のプレイヤーがすべてのアイテムを取得できない場合があります。

25人のプレーヤーを獲得するには、回避FetchMode.JOINします(N + 1の問題を回避するには、マッピングファイルでバッチサイズを使用します)。

List<Player> first25Players = session
  .createCriteria(Players.class)
  .addOrder(Order.asc("playerID"))
  .setMaxResults(25)
  .list();

25個のアイテムを取得するには、プレーヤーではなくアイテムごとにクエリを開始します。

List<Item> first25Items = session
  .createCriteria(Item.class)
  .addOrder(Order.asc("player")) // assuming that player is available
  .setMaxResults(25)
  .list();

アイテムからプレーヤーへのナビゲーションがない場合は、追加できます。

于 2011-06-16T06:55:12.130 に答える