2012-04-18 23 views
5

Hibernateを使用してテーブルから約1億行を取得しようとしています。私は内部のフィーのコレクションを含む永続化エンティティアイテムを持っています(別の永続化エンティティ)。私がに返すと、すべてのオブジェクトの料金にアクセスし、n + 1の問題を避けるために熱心に手数料を取っていきたいと考えています。HibernateでScrollableResultsを使ってコレクションを取得しようとしています。

また、私はプロバイダ(1対1のマッピングが、外部キー)と呼ばれる別のテーブルにそれを参加したいことを言及する必要があります。私は試しました:

String query = "select new " + Order.class.getName() 
      + "(i, p) from Item i left join fetch i.fees f, Provider p where " 
      + "p.factoryId=i.factoryId and p.factoryRef=i.factoryRef"; 

return session.createQuery(query).scroll(); 

My Orderクラスには、ProviderフィールドとItemフィールドが含まれています。私はとプロバイダ(即時にフェッチ手数料で)項目が含まれている注文のスクロール可能なリストで終わるしたい

Caused by: org.hibernate.QueryException: query specified join fetching, but the owner of the fetched association was not present in the select list

:私はこのエラーを取得します。

答えて

1

SelectClauseからこのコードは、あなたの悩みの原因となります。 fromElementsForLoad.contains(origin)

は、おそらく彼らは冗長は、その性能にあなたに多くの費用がかかります参加することからあなたを守るためにそれをやりました。あなたが決してそれを使用しないなら、連想をフェッチする理由がないので、良いことです。

あなたのケースでは、を新しいOrder.classにラップすると、クエリで装飾フィールドの親をフェッチするという事実は隠されています。

私はこれを検証することはできませんので、私は、現時点では何のデバッグ能力を持っていません。 SelectClause.classからこの正確な行をデバッグしようとし、fromElementsForLoadコレクションが保持する要素を確認してください。

私は、クエリ後Order.classを初期化推薦するN + 1問題を回避したい場合。アイテムとプロバイダのみを選択できます。

あなたがこれを検証できない場合、私は来週、適切なコンピュータに取得し、私の答えを拡張します。

+0

この回答は正しいと思います。もしそうなら、 'Order'を作るのではなく' List'を返すようにクエリを変更して 'Item'sを実際にフェッチしていることをHibernateに知らせることができます。これで、 'Order'を手動で作成する必要があります。 –

0

left join fetch i.fees fを削除し、マッピングでフェッチ熱心にやってみてください。

if (!fromElementsForLoad.contains(origin)) { 
         throw new QueryException(
           "query specified join fetching, but the owner " + 
           "of the fetched association was not present in the select list " + 
           "[" + fromElement.getDisplayText() + "]" 
         ); 

あなたが見ることができるように、フェッチキーワードが言及されたとき、あなたはフェッチ飾らフィールド親を求めているかどうかをチェックを休止状態:

関連する問題