回答:
私は主に動的クエリの基準クエリを好みます。たとえば、いくつかのパラメータに応じて、動的に順序を追加したり、一部の部分(制限など)を省略したりする方がはるかに簡単です。
一方、静的および複雑なクエリにはHQLを使用しています。これは、HQLの理解と読み取りがはるかに簡単だからです。また、HQLは、たとえば、さまざまな結合タイプに対して、もう少し強力だと思います。
HQLとcriteriaQueryの間にはパフォーマンスの点で違いがあります。criteriaQueryを使用してクエリを実行するたびに、DBの最後にクエリされたキャッシュに反映されないテーブル名の新しいエイリアスが作成されます。これにより、生成されたSQLをコンパイルするオーバーヘッドが発生し、実行に時間がかかります。
フェッチ戦略について[http://www.hibernate.org/315.html]
- 基準は、マッピングの遅延設定を尊重し、ロードしたいものがロードされることを保証します。つまり、1つのCriteriaクエリによって、複数のSQL即時SELECTステートメントが実行され、すべての遅延のないマップされた関連付けとコレクションを含むサブグラフがフェッチされます。「方法」、さらには「内容」を変更する場合は、setFetchMode()を使用して、特定のコレクションまたは関連付けの外部結合フェッチを有効または無効にします。条件クエリは、フェッチ戦略(結合vs選択vs副選択)を完全に尊重します。
- HQLはマッピングの遅延設定を尊重し、ロードしたいものがロードされることを保証します。つまり、1つのHQLクエリによって、複数のSQL即時SELECTステートメントが実行され、すべての遅延のないマップされた関連付けとコレクションを含むサブグラフがフェッチされます。「方法」と「何」かを変更する場合は、LEFT JOIN FETCHを使用して特定のコレクションの外部結合フェッチを有効にするか、null可能な多対1または1対1の関連付けを有効にするか、JOIN FETCHを使用して有効にします。 nullを許容しない多対1または1対1の関連付けのための内部結合フェッチ。HQLクエリは、マッピングドキュメントで定義されているfetch = "join"を尊重しません。
基準はオブジェクト指向のAPIですが、HQLは文字列の連結を意味します。つまり、オブジェクト指向のすべての利点が適用されます。
HQLはSQLに非常によく似ているため(ほとんどの開発者はすでによく知っています)、これらの「覚えておく必要はない」引数はそれほど重要ではありません。HQLがより異なる場合、これはより重要になります。
どのデータでどの入力が使用されるかわからない場合は、通常、基準を使用します。ユーザーが1〜50個の項目を入力できる検索フォームのように、私は彼らが何を検索するのか知りません。ユーザーが何を検索しているかをチェックするので、基準にさらに追加するのは非常に簡単です。そのような状況でHQLクエリを配置するのは少し面倒だと思います。HQLは素晴らしいですが、自分が何を求めているかを正確に理解しているときは。
HQLは、読みやすく、Eclipse Hibernateプラグインなどのツールを使用してデバッグしやすく、ログに記録しやすくなっています。基準クエリは、多くの動作が実行時に決定される動的クエリを構築するのに適しています。SQLがわからない場合は、基準クエリを使用して理解できますが、全体として、事前に必要なものがわかっている場合はHQLを好みます。
基準は、2次クエリキャッシュの特別な最適化を利用する自然なキー検索を指定する唯一の方法です。HQLには、必要なヒントを指定する方法がありません。
ここでいくつかの詳細情報を見つけることができます:
基準APIは、Hibernateの優れたコンセプトの1つです。私の見解によれば、これらはHQLとCriteria Apiを区別できるいくつかのポイントです
limit offset:rows
SQLインジェクションを回避することですsetParameter
私にとって、基準はダイナミッククエリを理解して作成するのが非常に簡単です。しかし、これまでに述べた欠点は、FetchModeにはSelect、Proxy、Defaultの3つのタイプしかないため、多対1などのリレーションをすべてロードし、これらすべての場合に多対1をロードすることです(そうすると、私は間違っている可能性があります)私を出します:))
基準と第二の問題は、それが完全にEmployeeオブジェクトを思い付くと、私はこれによることからEMPNAMEを得ることができinstedそれは私が従業員のちょうど負荷EMPNAMEにしたい場合には、この思い付く文句を言わない、すなわち完全なオブジェクトをロードすることで、それは本当に悪いで働きます報告する。ここで、HQLは必要なものだけをロードする(関連付け/関係をロードしなかった)ので、パフォーマンスを何度も向上させます。
基準の1つの機能は、動的なクエリ生成のためにSQLインジェクションからuを保護することです。HQLと同様に、urクエリは固定またはパラメーター化されているため、SQLインジェクションから安全ではありません。
また、ur aspx.csファイルでHQLを記述した場合、ur DALと密接に結合されます。
全体的に私の結論は、レポートのようにHQLなしでは生活できない場所があるので、それらを使用することです。
Criteria APIは、動的に生成されるクエリに適しています。そのため、WHERE句フィルター、JOIN句を追加したり、ORDER BY句やプロジェクション列を変更したりする場合、Criteria APIは、SQLインジェクション攻撃を防ぐ方法でクエリを動的に生成するのに役立ちます。
一方、この記事で説明するように、基準クエリは表現力が低く、非常に複雑で非効率的なSQLクエリにつながる可能性さえあります。
JPQLはJPA標準エンティティクエリ言語であり、HQLはJPQLを拡張し、Hibernate固有の機能をいくつか追加します。
JPQLとHQLは非常に表現力があり、SQLに似ています。Criteria APIとは異なり、JPQLおよびHQLでは、JPAプロバイダーによって生成される基になるSQLクエリを簡単に予測できます。また、CriteriaクエリよりもHQLクエリを確認する方がはるかに簡単です。
JPQLまたはCriteria APIでエンティティを選択することは、それらを変更する必要がある場合に意味があることに注意してください。それ以外の場合、DTOプロジェクションがはるかに適しています。
エンティティクエリ構造を変更する必要がない場合は、JPQLまたはHQLを使用します。フィルタリングや並べ替えの基準を変更したり、射影を変更したりする必要がある場合は、Criteria APIを使用してください。
ただし、JPAまたはHibernateを使用しているからといって、ネイティブSQLを使用してはならないという意味ではありません。SQLクエリは非常に便利で、JPQLとCriteria APIはSQLの代わりにはなりません。チェックアウトこの記事をこのトピックの詳細については。
私にとって、Criteriaの最大の勝利はサンプルAPIで、オブジェクトを渡すことができ、Hibernateはそれらのオブジェクトプロパティに基づいてクエリを構築します。
それ以外に、基準APIには以下のような癖があります(私は休止状態のチームがapiを作り直していると思います)。
sql(users from status = 'blocked'から削除)と同様のクエリが必要な場合はHQLを使用する傾向があり、文字列の追加を使用したくない場合は条件を使用する傾向があります。
HQLのもう1つの利点は、すべてのクエリを事前に定義でき、さらにファイルなどに外部化できることです。
基準APIは、SQLもHQLも提供しない1つの明確な機能を提供します。すなわち。クエリのコンパイル時チェックを可能にします。
最初はアプリケーションで主にCriteriaを使用しましたが、パフォーマンスの問題のためにHQLに置き換えられました。
主に、いくつかの結合を持つ非常に複雑なクエリを使用しています。これにより、基準で複数のクエリが発生しますが、HQLで非常に最適化されています。
完全なオブジェクトではなく、特定のオブジェクトに対していくつかのプロパティを使用する場合です。Criteriaでは、問題は文字列の連結でもありました。
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();
したがって、この場合、返されるレコードは必要なプロパティのマップです。
CriteriaUpdate<T>
しCriteriaDelete<T>
てください。
動的に条件クエリを実行すると、入力に基づいてクエリを作成できます。Hqlクエリの場合、作成したクエリは静的クエリなので、クエリの構造を変更することはできません。
HQLは、SQLインジェクションなどのセキュリティ上の問題を引き起こす可能性があります。