2011-04-03 11 views
7

私はHibernateでHQLクエリを使用していますが、クエリを再利用するアプリの性能を向上させることができるかどうかは不思議です。Hibernateでクエリを再利用する

通常は、セッションごとに新しいクエリオブジェクトを作成する必要があります。

Session session; 
Query q1 = session.createQuery("select a from Article a where id=:id"); 
q1.setInteger("id",123); 
List result = q1.list(); 

今、私は何度も何度も解析されているにしたくないHQLでは比較的複雑なクエリを、持っています。クエリを作成し、別のセッションでそれを再利用する方法はありますか?このように:Hibernateがとにかくプリペアドステートメントを使用している場合

Session session; 
Query q2 = q1.reattach(); 
q2.setInteger("id",123); 
List result = q2.list(); 

、これは特に準備された文をキャッシュするのConnectionPoolとの組み合わせで、顕著なパフォーマンスの向上でなければなりません。

EDIT:クエリプランがすでにQueryPlanCacheクラスにキャッシュされているため、通常はHibernateでのクエリの再利用は必要ありません。名前付きクエリは、クエリ文字列を検索するためだけに使用され、プランが関連付けられていないため、改善も提供されません。

結論:Hibernateでのクエリの再利用には使用できません。必ずパラメータ化されたクエリを使用するようにしてください。プランのキャッシュを小さくしてください。

+0

@allingeek:正確には何ですか? HibernateソースからQueryPlanCacheを開くだけです。それともあなたは何を意味しましたか? – Daniel

+0

私が本当に探していたのは、PreparedStatementの再利用でした。あなたの質問に基づいてc3p0のステートメントキャッシュ構成を追い詰め、その日を保存しました。ありがとう。 – allingeek

答えて

4

あなたは「名前付き問合せ」を使用することができます:起動

@Entity 
@NamedQuery(name="Article.findById", query="select a from Article a where id=:id")  
public class Article{ ... 

のようなあなたのエンティティクラスを注釈し、それを一度に解析されます、あなたはそれを使用していつでもあなたは、単に呼び出す:

session.getNamedQuery("Article.findById") 
     .setInteger("id",123); 
+1

許されていますが、役に立たないものです:)。私の質問に私の編集を参照してください。 – Daniel

0

名前付きクエリdescribed by Kiavashとは何を求めているのですか?しかし、それはあなたにあらゆる種類の重要なパフォーマンス向上を与えることは疑いの余地があります。

プリペアドステートメントは、Hibernateの名前付きクエリを使用しているかどうかにかかわらず、データベースがそれらをサポートしている場合に使用されます。ほとんどの場合、HQLクエリの解析の手間が省けます。名前付きクエリは、コードの再利用を目的としています。

+1

これはまさに私の意図でした。私はすでにデータベース内で準備されたステートメントを使用しており、残りのCPU時間の大部分がクエリのHQLの作業に費やされていることを知っています。 – Daniel