2

私たちが実行するクエリの中には、100,000 以上の結果があり、それらをロードしてクライアントに送信するのに永遠にかかるものがあります。そのため、ScrollableResults を使用して、ページ化された結果機能を使用しています。しかし、約 50,000 の結果を超えています (結果の数がまったく同じになることはありません)。

私は Oracle 10 ドライバーを使用して Oracle9i データベースを使用しており、Hibernate は Oracle9 ダイアレクトを使用するように構成されています。最新のJDBCドライバー(ojdbc6.jar)で試したところ、問題が再現されました。

また、いくつかのアドバイスに従い、注文句を追加しましたが、問題は再現されました。

以下は、私たちが何をするかを示すコード スニペットです。

final int pageSize = 50;
Criteria crit = sess.createCriteria(ABC.class);
crit.add(Restrictions.eq("property", value));
crit.setFetchSize(pageSize);
crit.addOrder(Order.asc("property"));
ScrollableResults sr = crit.scroll();
...
...
ArrayList page = new ArrayList(pageSize);
do{
  for (Object entry : page)
    sess.evict(entry); //to avoid having our memory just explode out of proportion
  page.clear();
  for (int i =0 ; i < pageSize && ! metLastRow;  i++){
    if (sr.next())
      page.add(sr.get(0));
    else 
      metLastRow = true;
  }
  metLastRow = metLastRow?metLastRow:sr.isLast();

  sendToClient(page);
}while(!metLastRow);

では、なぜ結果セットを取得して、最後にもっと多くの結果が必要なのかを教えてくれるのでしょうか?

4

2 に答える 2

1

あなたのコード スニペットには、resultSetやの定義などの重要な部分がありませんpage。しかし、とにかく、ラインはすべきではないのだろうか

if (resultSet.next())

むしろ

if (sr.next())

?

補足として、私の知る限り、永続化コンテキストから余分なオブジェクトをクリーンアップするには、呼び出すだけで実現できます

session.flush();
session.clear();

オブジェクトのコレクションをループしてそれぞれを個別に削除する代わりに。(もちろん、これにはクエリが独自の独立したセッションで実行される必要があります。)

更新: OK、次の推測ラウンド:-)

どの行がクライアントに送信されるかを実際に確認し、それを DB に対する同等の SQL クエリの結果と比較できますか? このコードが結果セット全体から特定の制限までのすべての行を取得するか、またはいくつかの行のみ (2 番目ごとなど) を取得するか (およびクライアントに送信するか)、または ... ルートに光を当てることができるかどうかを知っておくとよいでしょう。原因。

あなたが試すことができるもう一つのことは

crit.setFirstResults(0).setMaxResults(200000);
于 2010-04-05T12:14:27.453 に答える