JPAおよびHibernate-基準とJPQLまたはHQL


295

基準またはHQLを使用する場合の長所と短所は何ですか?Criteria APIはHibernateでクエリを表現するための優れたオブジェクト指向の方法ですが、CriteriaクエリはHQLよりも理解/構築が難しい場合があります。

いつ基準を使用し、いつHQLを使用しますか?どのユースケースで何を好みますか?それとも単に好みの問題ですか?


正しい答えは「ユースケースに依存する」でしょう。
Hace、2011年

そして、このツールはどうですか?オブジェクトの方法で一般的なクエリを作成できます:protected句select(){return em.select( "DISTINCT i").from(this.getName()、 "i").joinFetch( "i.locale lf") } public T findBySlug(String slug){return(T)this.select().join( "i.locale l"); .where( "l.slug =?"、slug).fetchSingle(); }
Vojtěch

1
意見ベースの質問の定義、それでも人々はそれを閉じる機会を取りませんでした...サイトのFAQ

回答:


212

私は主に動的クエリの基準クエリを好みます。たとえば、いくつかのパラメータに応じて、動的に順序を追加したり、一部の部分(制限など)を省略したりする方がはるかに簡単です。

一方、静的および複雑なクエリにはHQLを使用しています。これは、HQLの理解と読み取りがはるかに簡単だからです。また、HQLは、たとえば、さまざまな結合タイプに対して、もう少し強力だと思います。


13
また、Criteriaは少しタイプセーフに見えますが、安全だと感じることができるのはテストだけです。

特定の場合にHQLが基準APIよりも優れている理由を示す良い例はありますか?あるブログの終わりを読みましたが、何もわかりませんでした。あなたが助けることができればそれをいただければ幸いです。ありがとう。リンク-javalobby.org/articles/hibernatequery102
Erran Morad

上記のすべての理由-プログラマにとって安全であり、コーディングエラーが減少するため、HQLよりも基準を優先します-HQL文字列でのコンパイルは検証されません。
nuno 2014

ただし、ページ分割しながら個別のエンティティを取得するという問題があります。これを行うとき、問題を回避するためにHQLを選びます...
Anthony Webster

列名のメタモデルで条件クエリを使用すると、リファクタリング中に何も壊れないようになり、最新のIDEからの単純なコマンドを使用して、コード内のすべての出現箇所の名前を変更できます。
Massimo

92

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"を尊重しません。

1
閲覧している人を指摘するだけです。この回答は2008年からのものです。これはもう当てはまらないかもしれません。dimovelev.blogspot.com/2015/02/...
Amalgovinus

41

基準はオブジェクト指向のAPIですが、HQLは文字列の連結を意味します。つまり、オブジェクト指向のすべての利点が適用されます。

  1. 他のすべてが等しい場合、オブジェクト指向バージョンはエラーが発生しにくくなります。古い文字列はHQLクエリに追加される可能性がありますが、有効なCriteriaオブジェクトのみがCriteriaツリーに追加できます。事実上、Criteriaクラスはより制約されています。
  2. オートコンプリートを使用すると、オブジェクト指向はより発見しやすくなります(したがって、少なくとも私にとっては使いやすくなります)。クエリのどの部分がどこにあるかを必ずしも覚えておく必要はありません。IDEがお手伝いします
  3. また、構文の詳細(どのシンボルがどこにあるかなど)を覚えておく必要もありません。知っておく必要があるのは、メソッドの呼び出し方法とオブジェクトの作成方法だけです。

HQLはSQLに非常によく似ているため(ほとんどの開発者はすでによく知っています)、これらの「覚えておく必要はない」引数はそれほど重要ではありません。HQLがより異なる場合、これはより重要になります。


12
これらの議論は(HQLに関して)水を保持しません。文字列の連結を伴う必要はありません。OOバージョンがエラーを起こしにくいことは実証されていません。同様にエラーが発生しやすくなりますが、種類が異なります。呼び出しにどのような方法を知る努力がHQLに呼び出すためにどのようなシンボルを知ることからそれほど違いはありません(私は真剣に、私たちはここに偏微分方程式を解いていない、を意味します。)
luis.espinal

特定の場合にHQLが基準APIよりも優れている理由を示す良い例はありますか?あるブログの終わりを読みましたが、何もわかりませんでした。あなたが助けることができればそれをいただければ幸いです。ありがとう。リンク-javalobby.org/articles/hibernatequery102
Erran Morad

1
HQLの名前付きクエリはデプロイ時にコンパイルされ、この時点で欠落しているフィールド(おそらくリファクタリングが悪い場合)が検出されます。これにより、コードの復元力が向上し、実際には基準よりもエラーが発生しにくくなります。
narduk 2015

プロパティは単なる文字列であるため、Criteriaのオートコンプリートはほとんど役に立ちません。
Lluis Martinez

35

どのデータでどの入力が使用されるかわからない場合は、通常、基準を使用します。ユーザーが1〜50個の項目を入力できる検索フォームのように、私は彼らが何を検索するのか知りません。ユーザーが何を検索しているかをチェックするので、基準にさらに追加するのは非常に簡単です。そのような状況でHQLクエリを配置するのは少し面倒だと思います。HQLは素晴らしいですが、自分が何を求めているかを正確に理解しているときは。


1
これは良いコメントです。現在、結合を介して多くの異なるオブジェクトを含む検索フォーム用に非常に大きなHQL文字列を作成しています。醜く見えます。Criteriaがそれをクリーンアップできるかどうかを確認します。興味深い...
cbmeeks

ありがとう。これは優れた例です。もう少し教えてもらえますか?
Erran Morad 2014

31

HQLは、読みやすく、Eclipse Hibernateプラグインなどのツールを使用してデバッグしやすく、ログに記録しやすくなっています。基準クエリは、多くの動作が実行時に決定される動的クエリを構築するのに適しています。SQLがわからない場合は、基準クエリを使用して理解できますが、全体として、事前に必要なものがわかっている場合はHQLを好みます。



21

基準APIは、Hibernateの優れたコンセプトの1つです。私の見解によれば、これらはHQLCriteria Apiを区別できるいくつかのポイントです

  1. HQLはデータに対して選択操作と非選択操作の両方を実行しますが、基準はデータを選択するためだけのものであり、基準を使用して非選択操作を実行することはできません。
  2. HQLは静的クエリの実行に適していますが、基準は動的クエリの実行に適しています。
  3. HQLはページネーションの概念をサポートしていませんが、基準を使用してページネーションを実現できます。
  4. 基準は、HQLよりも実行に時間がかかりました。
  5. 基準では、動的なクエリ生成のため、SQLインジェクション使用しても安全ですが、HQLでは、クエリが固定またはパラメーター化されているため、SQLインジェクションによる安全性はありません。

11
HQLにはいくつかのポイントページネーションがあります。使用できるのはHQLでlimit offset:rows SQLインジェクションを回避することですsetParameter
Viswanath Lekshmanan 2015年

13

両方の長所を活用するには、HQLの表現力と簡潔さ、およびCriteriaの動的な性質から、Querydslの使用を検討してください

Querydslは、JPA / Hibernate、JDO、SQL、およびコレクションをサポートしています。

私はQuerydslのメンテナーなので、この答えは偏っています。


13

私にとって、基準はダイナミッククエリを理解して作成するのが非常に簡単です。しかし、これまでに述べた欠点は、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なしでは生活できない場所があるので、それらを使用することです。


13
HQLはSQLインジェクションに対して安全ではありません
Varun Mehta

基準は注射に対して安全ではないと思います。ここに私の記事を参照してください。stackoverflow.com/questions/6746486/...
ミスター・スミス

4
HQLは「setParameter」を追加することでSQLインジェクションを安全に
Javatar

2
@Zafar:あなたは投影を使用して、エンティティの特定のプロパティのみを選択することができます
はRazvanフラウィウスパンダ

@Zafarでは、特定の列を選択するために、条件クエリで射影を設定できます。EmpNameをフェッチできます。オブジェクト全体をフェッチする必要はありません。
Khatri

12

基準API

Criteria APIは、動的に生成されるクエリに適しています。そのため、WHERE句フィルター、JOIN句を追加したり、ORDER BY句やプロジェクション列を変更したりする場合、Criteria APIは、SQLインジェクション攻撃を防ぐ方法でクエリを動的に生成するのに役立ちます。

一方、この記事で説明するように、基準クエリは表現力が低く、非常に複雑で非効率的なSQLクエリにつながる可能性さえあります。

JPQLおよびHQL

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の代わりにはなりません。チェックアウトこの記事をこのトピックの詳細については。



11

私にとって、Criteriaの最大の勝利はサンプルAPIで、オブジェクトを渡すことができ、Hibernateはそれらのオブジェクトプロパティに基づいてクエリを構築します。

それ以外に、基準APIには以下のような癖があります(私は休止状態のチームがapiを作り直していると思います)。

  • a。criteria.createAlias( "obj")は、可能な外部結合ではなく内部結合を強制します
  • 同じエイリアスを2回作成することはできません
  • 一部のSQL句には対応する単純な基準がない(副選択のような)

sql(users from status = 'blocked'から削除)と同様のクエリが必要な場合はHQLを使用する傾向があり、文字列の追加を使用したくない場合は条件を使用する傾向があります。

HQLのもう1つの利点は、すべてのクエリを事前に定義でき、さらにファイルなどに外部化できることです。


9

基準APIは、SQLもHQLも提供しない1つの明確な機能を提供します。すなわち。クエリのコンパイル時チェックを可能にします。


7

最初はアプリケーションで主に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();

したがって、この場合、返されるレコードは必要なプロパティのマップです。


1
Criteriaを使用すると、org.hibernate.criterion.CriteriaSpecification.ALIAS_TO_ENTITY_MAP
AA

私の経験でマップのリストを返すと、パフォーマンスが非常に低下します。オブジェクト配列のリストまたはBeanのリストを返すことを好みます(特定の結果セットに適したBeanをいつでも定義できます)。
Lluis Martinez

7
  • HQLはデータに対して選択操作と非選択操作の両方を実行しますが、基準はデータを選択するためだけであり、基準を使用して非選択操作を実行することはできません
  • HQLは静的クエリの実行に適していますが、基準は動的クエリの実行に適しています。
  • HQLはページネーションの概念をサポートしていませんが、基準を使用してページネーションを実現できます
  • HQLよりも実行に時間がかかる基準を使用
  • Criteriaでは、動的なクエリ生成のため、SQLインジェクションを使用しても安全ですが、HQLではクエリが固定またはパラメーター化されているため、SQLインジェクションからの安全性はありません。

ソース


明確にするために、クエリにはHibernateのCriteria APIを使用した条件クエリが利用できる場合がありますが、JPA条件クエリは選択、更新、削除をカバーしています。を参照CriteriaUpdate<T>CriteriaDelete<T>てください。
Naros

5

動的に条件クエリを実行すると、入力に基づいてクエリを作成できます。Hqlクエリの場合、作成したクエリは静的クエリなので、クエリの構造を変更することはできません。


2
そうではありません。HQLでは、 ':'識別子を使用してプロパティを設定し、それらのプロパティを一意の値に置き換えることができます。たとえば、Query q = session.createQuery( "SELECT:aValue FROM my_table"); 次にq.setParameter( "aValue"、 "some_column_name");
MattC、2013年

@MattCこの例では、クエリの構造ではなく、パラメータの値を変更しています。
Czar

4

ここで死んだ馬を蹴りたくはありませんが、Criteriaクエリは現在非推奨になっていることに言及することが重要です。HQLを使用します。


1

また、動的クエリには基準クエリを優先します。しかし、私はhqlを削除クエリに好んでいます。たとえば、親ID 'xyz'の子テーブルからすべてのレコードを削除する場合、HQLによって簡単に達成できますが、基準APIの場合、最初にn個の削除クエリを起動して、nが子の数であることを確認する必要がありますテーブルレコード。


0

ここでのほとんどの答えは誤解を招くものであり、Criteria Queriesは遅いと言及していますがHQL、実際にはそうではありません。

詳細に調べていくつかのテストを実行すると、基準クエリが通常のHQLよりもはるかに優れたパフォーマンスを発揮することがわかります。

また、基準クエリを使用すると、HQLにはないオブジェクト指向コントロールを取得できます。

詳細については、こちらの回答をご覧ください


0

別の方法があります。元の休止状態の構文に基づいてHQLパーサーを作成して、最初にHQLを解析してから、動的パラメーターを動的に挿入したり、HQLクエリにいくつかの一般的なフィルターを自動的に追加したりしました。それはうまくいきます!


0

この投稿はかなり古いものです。ほとんどの回答は、JPA基準ではなく、休止状態基準について話します。JPA 2.1は、CriteriaDelete / CriteriaUpdate、および正確に何をフェッチするかを制御するEntityGraphを追加しました。Javaがオブジェクト指向であるため、基準APIの方が優れています。そのため、JPAが作成されます。JPQLをコンパイルすると、SQLに変換される前にASTツリー(OOモデル)に変換されます。


-3

HQLは、SQLインジェクションなどのセキュリティ上の問題を引き起こす可能性があります。


11
これらの問題はHQLによって引き起こされるのではなく、基本的なソフトウェア開発プラクティスの理解の欠如によって引き起こされます。基準APIを使用してSQLインジェクション攻撃を受けやすいコードを作成することもできます。
Jens Schauder 2013年

1
これは、「SQLインジェクションのセキュリティ上の問題を引き起こす可能性がありますJavaからRDBMSを照会」と言ってようなものだ:D
皇帝
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.