1。エンティティオブジェクトクエリ
エンティティオブジェクトクエリは、HQLクエリの基礎です。オブジェクトクエリ言語として、クエリ操作中のSQLとは異なります。クエリ文字列のコンテンツは、クラス名とクラス属性名に置き換える必要があります。このクエリ方法は比較的簡単です。 SQLスキルがある限り、HQLを使用するのは非常に簡単です。ただし、注意が必要な問題はいくつかあります。つまり、データのクエリと取得は目的ではありません。考慮する必要があるのは、効率的なクエリステートメントを作成する方法です。これは議論の焦点です。
1.N+1の問題
(1)N+1の問題は何ですか
この名詞を初めて聞いたとき、疑問があるかもしれません。 N+1の問題について聞いたことがありません。それで、それはどういう意味ですか? n+1はテーブル内のnデータを参照するため、これらのnデータを取得すると、n+1 sqlコマンドが生成されます。この操作はn+1と呼ばれます。ここで、1はIDリストを検索するステートメントの発行を指し、nは関連するオブジェクトをロードするためにIDに基づいてn SQLステートメントを発行することを指します。この種のクエリ操作は非常に非効率的であり、多くの場合、イテレーターで生成されます。つまり、クエリの結果を反復因子に直接変換すると、次のようにこの問題が発生します。
public void testquery(){session session = null; try {session = hibernateutils.getSession(); session.begintransaction(); /*** n+1の問題があります。いわゆるn+1値は、n+1 SQLステートメントを発行することです** 1:IDリストを照会するステートメント*** N:IDに基づいて発行n SQLステートメントを発行し、関連するオブジェクト*/ iterator iter = session.createquery( "from Student")。 while(iter.hasnext()){desute sustent =(student)iter.next(); system.out.println(sustent.getName()); } session.getTransaction()。compid(); } catch(Exception e){e.printstacktrace(); session.getTransaction()。rollback(); }最後に{hibernateutils.closessession(session); }}上記のクエリコードは、クエリがイテレーターとして返されるため、n+1の問題を引き起こします。そのため、1回生成されない場合はSQLステートメントが発行されます。これは主に、キャッシュからデータを照会するイテレーターのクエリメカニズムに依存します。データがキャッシュに存在しない場合、データは最初にメモリに変換されるため、この時点でSQLクエリステートメントが発行されるため、SQLステートメントがすべての反復を生成します。この書き込み方法は実際には間違いであり、他の方法を使用して最適化することができます。
(2)N+1の問題を避けます
n+1の問題は、反復の不適切な使用のために発生します。もちろん、この問題を回避するために他の方法を使用できます。これがリスト方法です。リストと反復の最大の違いは、リストがデータをキャッシュに入れるが、キャッシュを使用しないことです。デフォルトでは、リストは毎回SQLステートメントを発行します。 iterateを使用する前に、リストをデータベースに保存するためにリストを使用して、データにアクセスするときにキャッシュから読み取ることができ、n+1の問題の発生を回避できます。コードは次のとおりです。
public void testquery(){session session = null; try {session = hibernateutils.getSession(); session.begintransaction(); List Students = session.createquery( "from sudent")。list(); System.out.println("--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------その後、IDに基づくSQLステートメントクエリは発行されず、キャッシュ内のデータが直接使用されます * *データがパフォーマンスを改善する場合、N+1の問題が発生します * // system.out.println()session.getTransaction() }}上記の例では、リスト操作を実行した後、データがセッションキャッシュ(第1レベルのキャッシュ)に配置されるため、N+1の問題を回避します。したがって、ITERETを使用すると、IDリストを照会するためにステートメントが発行され、対応するデータがIDに従ってキャッシュにロードされます。キャッシュに一致するデータがある場合、IDに基づくSQLステートメントクエリは発行されなくなり、キャッシュ内のデータが直接使用されます。反復メソッドは、キャッシュにデータが存在する場合、パフォーマンスを改善できます。そうしないと、n+1の問題が発生します。
2。オブジェクトナビゲーションクエリ
オブジェクトナビゲーションとは、1つのオブジェクトのオブジェクトの属性ナビゲーションに従って、別のオブジェクトからデータを取得することを指します。これにより、クエリステートメントを簡素化し、クエリメソッドを最適化できます。通常のアイデアに従うと、別のクラスのオブジェクトを書き直して書き込み、別のオブジェクトの操作を取得できます。これは、オブジェクトナビゲーションステートメントを比較する方が面倒です。
@suppresswarnings({"unchecked"、 "rawTypes"})public void testquery1(){session session = null; try {session = hibernateutils.getSession(); session.begintransaction(); //結果セット属性リストを返す、エンティティクラスの要素タイプと属性タイプは同じリストであり、学生= session.createquery( "s.classes.name 'like'%2% '")。list(); for(iterator item = sustent.iterator(); ite.hasnext();){desute obj =(desute)ite.next(); System.out.println(obj.getName()); } session.getTransaction()。compid(); } catch(Exception e){e.printstacktrace(); session.getTransaction()。rollback(); }最後に{hibernateutils.closessession(session); }}上記の例のクエリステートメントは、オブジェクトナビゲーション法を使用します。クエリステートメントは、学生オブジェクトからの情報クエリですが、比較するオブジェクト属性はクラスオブジェクトの名前属性からのものです。現時点では、Object Navigation Queryメソッドを使用すると、クエリ効率が大幅に向上し、クエリステートメントが最適化されます。それが通常のクエリ方法である場合、多数の接続ステートメントが生成される場合がありますが、これは非常に複雑です。
2。SQLネイティブクエリ
ネイティブクエリ値は、HQLステートメントを使用するのではなく、SQLステートメントを使用してデータを取得および取得することです。その使用方法は、実際には非常に単純で、HQLと同様です。 createSqlqueryメソッドを使用してクエリする必要があります。実際には、HQLのCreateQueryメソッドに似ています。コードは次のとおりです。
public void testqeury(){session session = null; try {session = hibernateutils.getSession(); session.begintransaction();リストlist = session.createsqlquery( "select * from t_student")。list(); for(iterator item = list.iterator(); ite.hasnext();){object [] obj =(object [])ite.next(); System.out.println(obj [0]+"、"+obj [1]); } session.getTransaction()。compid(); } catch(Exception e){e.printstacktrace(); session.getTransaction()。rollback(); }最後に{hibernateutils.closessession(session); }}上記のコードでは、createsqlqueryメソッドを使用しています。メソッドのクエリ文字列はSQLステートメントです。基礎となる文字列クエリメソッドを実装します。違いは、HQLにはパッケージングの別の層があり、hibernate.cfg.xmlに対応する方言オプションを構成してマッピングを完了することです。
3。接続クエリ
接続クエリは、多くの場合、SQLで複数のオブジェクトのコレクションを取得するために使用されます。その中で、最も一般的に使用されるのは、内側の結合、右結合など、内側の結合クエリ、左外結合クエリ、および右外の結合クエリを指します。クエリ中に返すコンテンツは、エンティティ間のデカルト製品、クエリのコンテンツと左のテーブルのコンテンツ、クエリコンテンツと右のテーブルのコンテンツ、クエリ関数は強力です。 HQLの接続クエリメソッドとSQLの接続クエリはクエリ結果で同じですが、クエリステートメントにはわずかな違いがあります。
1。内部接続
HQLのイントラジョインクエリは、Inner JoinステートメントまたはJoinステートメントを使用して照会できます。 SQLイントラコネクションクエリと同様に、HQLのJoinクエリは、明示的で暗黙的な2つのタイプに分割されます。表示されたクエリは、クエリ文字列の結合キーワードを指します。暗黙のクエリでは、文字列に結合を追加する必要はありません。
//内部接続@suppresswarnings({"unchecked"、 "rawTypes"})public void testquery(){session session = null; try {session = hibernateutils.getSession(); session.begintransaction(); //結果セット属性リストを返す、エンティティクラスの要素タイプと属性タイプは同じリストであり、session.createquery( "Select s.name、c。name from Student s s.classes c")。リスト(); for(iterator item = sustent.iterator(); ite.hasnext();){object [] obj =(object [])ite.next(); System.out.println(obj [0]); } session.getTransaction()。compid(); } catch(Exception e){e.printstacktrace(); session.getTransaction()。rollback(); }最後に{hibernateutils.closessession(session); }}
2。外部接続
外部接続は、左外の接続と右外の接続クエリに分割されます。クエリメソッドは似ていますが、クエリの結果は異なります。これらは、クエリの結果におけるSQLの外部接続と同じです。違いはライティング方法です。特定のコードは次のとおりです。
@suppresswarnings({"unchecked"、 "rawTypes"})public void testquery(){session session = null; try {session = hibernateutils.getSession(); session.begintransaction(); //結果セット属性リストを返し、エンティティクラスの要素タイプと属性タイプは同じリストであり、session.createquery( "Select s.name、c。name from Student s Left Join s.classes c")。リスト(); for(iterator item = sustent.iterator(); ite.hasnext();){object [] obj =(object [])ite.next(); System.out.println(obj [0]); } session.getTransaction()。compid(); } catch(Exception e){e.printstacktrace(); session.getTransaction()。rollback(); }最後に{hibernateutils.closessession(session); }}上記のコードは、左外の結合クエリステートメントを使用します。対応する右外の結合クエリメソッドは、左外の結合に似ています。左に変換するだけです。クエリデータはリストオブジェクトに保存され、クエリコンテンツはリストを介して取得できます。
4。外部命名クエリ
外部の名前のクエリとは、クエリステートメントをマッピングファイルに記述し、<Query>タグを使用してマッピングファイルのHQLステートメントを定義することを指します。このようにして、定義されたHQLステートメントは関数構成関数を実現できます。問題がある場合は、構成を変更するだけです。このSQLステートメントを使用する場合は、次の例に示すように、プログラムでsession.getNamedQuery()メソッドを使用してHQLクエリ文字列を取得できます。
1。外部クエリステートメント
次の例は、外部クエリステートメントのアプリケーションを示し、マッピングファイルに<Query>タグを追加し、タグに名前属性を追加し、<![cdata []]>に文字列を追加して、クエリの名前属性に応じてプログラムで取得できるようにします。
<?xml version = "1.0"?> <!doctype hibernate-mapping public " - // hibernate/hibernateマッピングDTD 3.0 // en" "" http://hibernate.sourceforge.net/hibernate-mapting-3.0.dtd "テーブル= "t_student"> <id name = "id"> <generator // id> <プロパティ名= "name"/> <プロパティ名= "createtime"> </property> <! - 列名はクラスのリストと同じである必要があります。 name = "querystudent"> <![cdata [select s from sudent s s.id <? ]]> </query> </hibernate-mapping>
外部の名前のクエリは、クエリステートメントをマッピングファイルに配置するため、パブリッククエリ文字列と見なすことができます。これがその利点であるため、他のプログラムファイルを取得して使用できます。さらに、公開文字列としての変更の利便性を高めます。
2。プログラムアプリケーション
外部クエリステートメントを定義した後、プログラムでそれらを使用する必要があります。 HQLは、外部クエリステートメント文字列を取得するためのgetNameQueryメソッドを提供します。この方法に外部カーソル名を追加する必要があります。 HQLは、次のように、カーソル名に基づいて対応するSQLステートメントブロックを照会します。
//外部ネーミングクエリ@suppresswarnings({"unchecked"、 "rawTypes"})public void testquery(){session session = null; try {session = hibernateutils.getSession(); session.begintransaction();リスト= session.getNamedQuery( "QueryStudent")。SetParameter(0、10).list(); for(iterator item = sustent.ite.hasnext();){desute obj =(desute)ite.next(); System.out.println(obj.getName()); } session.getTransaction()。compid(); } catch(Exception e){e.printstacktrace(); session.getTransaction()。rollback(); }最後に{hibernateutils.closessession(session); }}