CriteriaまたはHQLを使用することの長所と短所は何ですか? Criteria API は、Hibernate でクエリを表現するための優れたオブジェクト指向の方法ですが、Criteria クエリは HQL よりも理解/構築が難しい場合があります。
Criteria と HQL はいつ使用しますか? どのユースケースで何を優先しますか? それとも単に好みの問題ですか?
私は主に動的クエリの基準クエリを好みます。たとえば、いくつかのパラメータに応じて、いくつかの順序を動的に追加したり、いくつかの部分 (制限など) を除外したりする方がはるかに簡単です。
一方、静的で複雑なクエリには HQL を使用しています。これは、HQL の方が理解しやすく読みやすいためです。また、HQL はもう少し強力だと思います。たとえば、さまざまな結合タイプに対してです。
HQL と criteriaQuery の間にはパフォーマンスの点で違いがあります。criteriaQuery を使用してクエリを起動するたびに、テーブル名の新しいエイリアスが作成されますが、これはどの DB に対しても最後にクエリされたキャッシュには反映されません。これにより、生成された SQL をコンパイルするオーバーヘッドが発生し、実行に時間がかかります。
フェッチ戦略について[http://www.hibernate.org/315.html]
- Criteria は、マッピングの遅延設定を尊重し、ロードしたいものがロードされることを保証します。これは、1 つの Criteria クエリによって、複数の SQL 即時 SELECT ステートメントが発生し、遅延マップされていないすべての関連付けとコレクションを含むサブグラフをフェッチする可能性があることを意味します。「方法」や「内容」さえも変更したい場合は、setFetchMode() を使用して、特定のコレクションまたは関連付けの外部結合フェッチを有効または無効にします。基準クエリは、フェッチ戦略 (結合、選択、副選択) も完全に尊重します。
- HQL は、マッピングの遅延設定を尊重し、ロードしたいものがロードされることを保証します。これは、1 つの HQL クエリが、すべての非遅延マッピングされた関連付けとコレクションを含むサブグラフを取得するために、複数の SQL 即時 SELECT ステートメントになる可能性があることを意味します。「どのように」、さらには「何を」変更したい場合は、LEFT JOIN FETCH を使用して、特定のコレクションまたは null 許容の多対 1 または 1 対 1 の関連付けの外部結合フェッチを有効にするか、JOIN FETCH を使用して有効にします。 null 非許容の多対 1 または 1 対 1 の関連付けの内部結合フェッチ。HQL クエリは、マッピング ドキュメントで定義された fetch="join" を尊重しません。
Criteriaはオブジェクト指向APIですが、HQLは文字列の連結を意味します。つまり、オブジェクト指向のすべての利点が適用されます。
HQLはSQL(ほとんどの開発者はすでによく知っています)に非常によく似ているため、これらの「覚えておく必要はありません」という引数はそれほど重要ではありません。HQLがもっと異なっていれば、これはもっと重要です。
私は通常、どの入力がどのデータに使用されるかわからない場合に Criteria を使用します。ユーザーが 1 から 50 の項目のいずれかを入力できる検索フォームのように、ユーザーが何を検索するのかわかりません。ユーザーが何を検索しているかを確認しながら、基準にさらに追加するのは非常に簡単です。その状況でHQLクエリを入れるのはもう少し面倒だと思います。HQLは、自分が何を望んでいるかを正確に知っている場合に最適です.
HQL ははるかに読みやすく、Eclipse Hibernate プラグインなどのツールを使用してデバッグしやすく、ログに記録しやすくなっています。基準クエリは、多くの動作が実行時に決定される動的クエリを作成する場合に適しています。SQL を知らなくても、Criteria クエリを使用することは理解できますが、全体として、必要なものが事前にわかっている場合は HQL を好みます。
基準は、第 2 レベルのクエリ キャッシュで特別な最適化を利用する自然キー ルックアップを指定する唯一の方法です。HQL には、必要なヒントを指定する方法がありません。
ここで詳細情報を見つけることができます:
Criteria Api は、Hibernate の優れたコンセプトの 1 つです。私の見解によると、これらはHQLとCriteria Apiを区別できる数少ないポイントです。
Criteria API は、動的に生成されるクエリに適しています。そのため、WHERE 句のフィルターや JOIN 句を追加したり、ORDER BY 句や射影列を変更したりする場合、Criteria API を使用すると、SQL インジェクション攻撃を防ぐ方法でクエリを動的に生成できます。
一方、Criteria クエリは表現力が低く、非常に複雑で非効率的な SQL クエリになる可能性さえあります。
JPQL は JPA 標準のエンティティクエリ言語であり、HQL は JPQL を拡張し、Hibernate 固有の機能をいくつか追加します。
JPQL と HQL は非常に表現力が高く、SQL に似ています。Criteria API とは異なり、JPQL および HQL を使用すると、JPA プロバイダーによって生成される基になる SQL クエリを簡単に予測できます。また、基準クエリよりも HQL クエリを確認する方がはるかに簡単です。
エンティティを変更する必要がある場合は、JPQL または Criteria API を使用してエンティティを選択することが理にかなっていることに注意してください。それ以外の場合は、DTO プロジェクションの方がはるかに適しています。
エンティティ クエリ構造を変更する必要がない場合は、JPQL または HQL を使用します。フィルタリングまたはソート基準を変更する必要がある場合、または射影を変更する必要がある場合は、Criteria API を使用してください。
ただし、JPA または Hibernate を使用しているからといって、ネイティブ SQL を使用してはならないというわけではありません。SQL クエリは非常に便利であり、JPQL と Criteria API は SQL の代わりにはなりません。
HQL の表現力と簡潔さ、および Criteria の動的な性質の両方の長所を活かすには、 Querydslの使用を検討してください。
Querydsl は、JPA/Hibernate、JDO、SQL、およびコレクションをサポートしています。
私は Querydsl のメンテナーなので、この回答は偏っています。
私にとって、基準は理解しやすく、動的クエリを作成するのは非常に簡単です。しかし、私がこれまでに言った欠陥は、選択、プロキシ、デフォルトの 3 種類の FetchModes しかないため、すべての多対一などの関係をロードし、これらすべてのケースで多対一をロードすることです (そうであれば私は間違っているかもしれません)私から:))
Criteria の 2 番目の問題は、完全なオブジェクトをロードすることです。つまり、従業員の EmpName をロードしたい場合は、完全な Employee オブジェクトを作成して、EmpName を取得できます。報告する。ここで、HQL は必要なものをロードするだけで (アソシエーション/リレーションをロードしませんでした)、パフォーマンスを何度も向上させます。
Criteria の特徴の 1 つは、クエリが固定またはパラメーター化されている HQL のように動的なクエリを生成するため、SQL インジェクションから安全ではないため、SQL インジェクションから安全であるということです。
また、aspx.cs ファイルに HQL を記述すると、DAL と密接に結合されます。
全体的な私の結論は、レポートのような HQL なしでは生きていけない場所があるので、それらを使用することです。
私にとって Criteria の最大のメリットは、サンプル API です。ここでは、オブジェクトを渡すことができ、hibernate はそれらのオブジェクト プロパティに基づいてクエリを作成します。
それに加えて、クライテリア API には癖があります (休止状態のチームが API を作り直していると思います)。
SQL に似たクエリが必要な場合は HQL を使用する傾向があり (status='blocked' のユーザーから削除)、文字列の追加を使用したくない場合は基準を使用する傾向があります。
HQL のもう 1 つの利点は、すべてのクエリを事前に定義し、それらをファイルなどに外部化することさえできることです。
Criteria API は、SQL も HQL も提供しない 1 つの明確な機能を提供します。すなわち。これにより、クエリのコンパイル時のチェックが可能になります。
最初はアプリケーションで主に Criteria を使用していましたが、パフォーマンスの問題により HQL に置き換えられました。
主に、いくつかの結合を含む非常に複雑なクエリを使用しているため、Criteria では複数のクエリが発生しますが、HQL では非常に最適化されています。
完全なオブジェクトではなく、特定のオブジェクトに対していくつかのプロパティのみを使用する場合があります。基準では、問題は文字列の連結でもありました。
HQL でユーザーの名前と姓を表示する必要がある場合、それは非常に簡単(name || ' ' || surname)
ですが、Crteria ではこれは不可能です。
これを克服するために、ResultTransormers を使用しました。ここでは、必要な結果のためにそのような連結が実装されているメソッドがありました。
現在、主に次のような HQL を使用しています。
String hql = "select " +
"c.uuid as uuid," +
"c.name as name," +
"c.objective as objective," +
"c.startDate as startDate," +
"c.endDate as endDate," +
"c.description as description," +
"s.status as status," +
"t.type as type " +
"from " + Campaign.class.getName() + " c " +
"left join c.type t " +
"left join c.status s";
Query query = hibernateTemplate.getSessionFactory().getCurrentSession().getSession(EntityMode.MAP).createQuery(hql);
query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
return query.list();
この場合、返されるレコードは必要なプロパティのマップです。
動的の基準クエリは、入力に基づいてクエリを構築できます。Hql クエリの場合、一度構築するとクエリの構造を変更することはできません。
ここで死んだ馬を蹴りたくはありませんが、Criteria クエリは現在非推奨であることに言及することは重要です。HQL を使用します。
ここでのほとんどの回答は誤解を招くものでありCriteria Queries
、HQL
実際にはそうではありません。
深く掘り下げていくつかのテストを実行すると、基準クエリが通常の HQL よりもはるかに優れたパフォーマンスを発揮することがわかります。
また、Criteria Queryを使用すると、 HQLにはないオブジェクト指向コントロールを取得できます。
詳細については、こちらの回答をお読みください。
別の方法があります。hibernate の元の構文に基づいて HQL パーサーを作成することになったので、最初に HQL を解析してから、動的パラメーターを動的に挿入したり、HQL クエリにいくつかの一般的なフィルターを自動的に追加したりできます。それはうまくいきます!