前回、関連操作を一緒に実行するために基準を使用する方法を学んだが、Hibernateが正式に推奨するクエリ方法ではないため、あまり使用しません。それでは、公式に推奨されるHQLを見て、それがどれほど強力かを学びましょう。
HQL、またはHibernate QueryステートメントとSQLの違いは何ですか? 1文字の違い、ハハ。
もちろん、そうではありません。 HQLとSQLの違いは、さまざまなアイデアにあります。 HQLはオブジェクト指向の方向を使用してクエリを使用し、SQLは2次元データベーステーブルのクエリを使用します。ここに含まれているのは、アイデアの違いです。 HQLは実際にはSQLであり、SQLを内部的に変換および生成するためにHibernateによって作成されます。
1)それ以上のADOなしで、その力を見てみましょう。
ユーザーから
このコードは非常によく知られています。なぜなら、SQLのテーブル名から使用することが多いためですが、ここでの違いは、ユーザーがここでテーブル名ではなく、エンティティクラスの名前とHibernateの名前がマッピングに役立つことです。
SQLステートメントを関連付けて、特定の属性を見つけ、特定の属性に従って条件付きで制限する場合、同様のステートメントを取得できます。
USR.AGE> 20およびUSR.AGE <60をユーザーからusr.name、usr.ageを選択してください
このようにして、20歳以下のユーザーの名前と年齢が60歳未満であることがわかりました。理解しやすいです。
and、または、like、<、>、= = and sqlステートメントはすべてHQLで使用できます。
複数の属性を照会すると、返された結果はオブジェクト[]配列であり、1つだけの属性である場合、オブジェクトが返されることに注意してください。これには異なる解析方法が必要なため、クエリするときはそれに注意を払う必要があります。
2)もちろん、HQLはオブジェクト指向であり、これを行うと、オブジェクト指向のアイデアではないと以前に述べました。変更しましょう:
ユーザーUSR.age> 20からusr.ageから新しいユーザー(usr.name、usr.age)を選択しますこのようにして、クエリ結果をユーザーオブジェクトに入れます。ここでは、ユーザーコンストラクターが呼び出されていることに注意してください。ユーザークラスで2つのパラメーターを受信するユーザーコンストラクターが必要です。そうしないと、エラーが報告されます。エラーメッセージはほぼ次のとおりです。
クラス[org.hibernate.tutorial.domain8.user]に適切なコンストラクターを見つけることができません。
適切なコンストラクターを見つけることができません。対応するパラメーターを受信するコンストラクターを追加するだけであることは非常に明確です。
対応するIDを確認したとき、知りませんでした。現時点でSaveOrUpDateメソッドを呼び出すと、実際に保存された操作が実行されました。
テストコードを見てみましょう。
上記のクエリステートメントを実行した後、次の操作を実行します。
while(iter.hasnext()){user user =(user)iter.next(); user.setname( "sun2"); session.saveorupdate(user); }この時点で、冬眠声明は次のとおりです。
hibernate:user(user_name、age)values(?、?)に挿入
更新ではなく、新しいものを挿入します。
次に、更新する必要がある場合は、一緒にIDを見つける必要があります。
Usr.age>(usrからselect avg(usr.age))からUsr.age where whereから新しいユーザー(usr.name、usr.age、usr.id)を選択してください)
ユーザーコンストラクターを変更することを忘れないでください。
この時点で、テストコードを再度実行すると、次のようになります。
hibernate:uspled userset user_name =?、age =? user_id =?
Usr.age>(usr.age(usr.age)をusrから選択)からusr.nameを選択してください)
このHQLは、平均年齢よりも古いユーザーの名前を検出します。
4)Hibernate 3では、最初にロードしてから2で削除することなく、オブジェクトを簡単に更新および削除できます。1つのステートメントで直接実行できます。
ユーザーセットname = '123123 'を更新するname =' sun33 '
ステートメントを削除します。
nemetユーザー= '123123'
5)冬眠をグループ化して並べ替えることも簡単です。グループを使用して注文するだけで、現時点ではこれについてはこれ以上話しません。
6)上記はクエリまたは更新に直接記述されていることがわかります。動的な割り当てが必要な場合、または割り当てが多すぎる場合、JDBCのような文字列をスプライスすることはできません。 5人以上がいると推定されており、プロジェクトチームの全員が私をscりたいと思っています。
最新の方法を使用し、代わりにプレースホルダーを使用して、特定の値を設定することをお勧めします。
私たちの直接コード:
query query = session.createquery( "usr.name =?"); query.setString(0、 "shun");
この方法は、直接使用する準備された測定に似ていることがわかります。 SET ***を介してセットされていますが、ここでの位置は0から始まり、準備が1から始まることです。ここで特に注意してください。
hibernate2にはセッションメソッドもありますが、現在3を使用しているので、それについてはあまり言いません。
上記で使用したプレースホルダーは注文プレースホルダーと呼ばれ、参照プレースホルダーと呼ばれる別のプレースホルダーがあります。見てみましょう:
クエリquery = session.createquery( "usr.name =:name"); usr.name =:name "); query.setParameter( "name"、 "shun");
私は次のようなものがあることを見ました:私たちのHQLステートメントに名前。これはリファレンスプレースホルダーです。後でSetParameterを介して値を設定するだけです。ここの最初のパラメーターは、HQLステートメントのプレースホルダー値に対応する必要があることに注意してください。
もちろん、一部の人々は、これがオブジェクト指向ではないと言うかもしれませんので、再びオブジェクト指向に行きましょう。
まず、クエリの値をカプセル化するためのクラスを作成します
Public Class userquery {private string name;プライベートインクエイジ; // get/setメソッドを省略} query query = session.createquery( "usr.name =:name"); userquery uq = new userquery(); uq.setname( "shun"); query.setProperties(UQ);このクラスを通じて直接クエリする必要がある値をカプセル化します。非常にオブジェクト指向。
一部のプロジェクトチームには、SQLステートメントがコードに表示されないという奇妙な規制がいくつかあります。これが仕様である場合、私が見た当社のすべてのコードは資格がありません。カップに多くの弦のスプライシングが落ちてしまうようになります。既存のプロジェクトを維持するために怪我をするのは本当に難しいです。
SQLステートメントはコードでは許可されていません。これは良い提案ですが、機会に依存します。 HibernateがファイルのマッピングでHQLを構成する方法を見てみましょう。
構成ファイルを直接確認してください。
<query name = "querybyname"> <![cdata [usr.name =:name]]> </query>
このようなタグを追加しました。これは、HQLステートメントであることを示しています。
このステートメントを取得する必要がある場合、コードに文を追加する必要があります。
クエリquery = session.getNamedQuery( "querybyname");
このようにして、HQLステートメントが取得されます。
HQLは、SQLの組み合わせを使用して、内側の結合、左外結合、右外の結合、完全結合など、クエリを使用することもできます。
彼らの使用法を見てみましょう:
最初にエンティティクラスを見てみましょう。テストで使用する必要があります。
パブリッククラスのチューザーは、シリアル化可能な{private static final long serialversionuid = 1l; private int id;プライベートインクエイジ;プライベート文字列名;プライベートセット<アドレス>アドレス= new Hashset <destress>(); // get/set method} public classアドレス実装serializable {private static final long serialversionuid = 1l; private int id;プライベート文字列アドレス。プライベートチューザーユーザー。 // get/set method}マッピングファイルを見てみましょう。
<hibernate-mapping package = "org.hibernate.tutorial.domain6"> <class name = "tuser" table = "t_user" insert = "true" dynamic-update = "true"> <id name = "id" column = "id"> <generator/>> </id> <property = "oppy"/> < name = "age" type = "java.lang.integer" column = "age"/> <set name = "addresses" cascade = "table =" t_address "inverse =" true "> <key column =" user_id "/> Package = "org.hibernate.tutorial.domain6"> <class name = "アドレス"テーブル= "t_address" dynamic-insert = "false" dynamic-update = "false" dynamic-update = "false" dynamic-update = "id" type = "java.lang.integer"> type = "java.lang.string"/> <nuly-one name = "user" column = "user_id" not-null = "true"> </muly-one> </class> </hibernate-mapping>
対応するパッケージ名を変更するだけです。
正式なテストを実施しましょう:
テストする前に、テーブルのデータを見てみましょう。
T_ADDRESSテーブルのデータは次のとおりです。
T_USERテーブルデータは次のとおりです。
1)最初に、内側の結合でフェッチされている内側の結合を見てみましょう。ここでの取得の意味は、必要なデータを取得することであることに注意してください。フェッチングが使用されない場合、取得したデータはオブジェクト[]データ型です。
最初に見てみましょう
TUSER USR Innerに参加してください
実行すると、冬眠出力は次のとおりです。
hibernate:id1_0_としてtuser0_.idを選択し、addresses1_.idはid0_1_、tuser0_.nameとしてname1_0_、tuser0_.age as age1_0_、address0_1_、address0_1_、address1_.user_id as user3_0_1_ t_addressアドレス1_ on tuser0_.id = addresses1_.user_id
MySQLで実行する際に結果を確認できます。
Hibernateがそれを内側の結合ステートメントに変換し、アドレスを見つけることがわかります。
対応するアドレスとレコードがないため、結果にShun4の記録はないことがわかります。
フェッチの代わりに内側の結合を使用する場合、それが印刷するステートメントは次のとおりです。
hibernate:id1_0_としてtuser0_.idを選択し、addresses1_.idはid0_1_、tuser0_.nameとしてname1_0_、tuser0_.age as age1_0_、adstress0_1_、address0_1_、address1_.user_id as user3_0_1_ tuser0_.id = addresses1_.user_id
ステートメントは違いはないようですが、それを見つけたとき、それはオブジェクト[]配列タイプを取得するため、この分析に注意を払う必要があります。
Fetchを使用しないが、内側の結合だけを使用する場合は、次のように解析する必要があります。
クエリquery = session.createquery( "tuser usr inner join usr.addresses");リストリスト= query.list(); iterator iter = list.iterator(); while(iter.hasnext()){object [] results =(object [])iter.next(); for(int i = 0; i <results.length; i ++){system.out.println(results [i]); }}印刷の結果が表示されます:
org.hibernate.tutorial.domain6.tuser@16925b0 org.hibernate.tutorial.domain6.address@914f6a org.hibernate.tutorial.domain6.tuser@787d6a org.hibernate.tutorial.domain6.dress6.dress@71dc3d org.hibernate.tutorial.domain6.tuser@1326484 org.hibernate.tutorial.domain6.address@16546ef
その結果はそれぞれ対応するオブジェクトです。
2)左外結合、これはSQLの左接続に相当します。例を直接見てみましょう。
チューザーUSRから左外の左外結合Fetch USR.Addresses
上記のステートメントを実行すると、冬眠が印刷します。
hibernate:id1_0_としてtuser0_.idを選択し、addresses1_.idはid0_1_、tuser0_.nameとしてname1_0_、tuser0_.age as age1_0_、adstress0_1_、address0_1_、address1_.user_id as user3_0_0_1_ t_addressアドレス1_ on tuser0_.id = addresses1_.user_id
MySQLで確認して見ました。
Shun4には対応するアドレスはありませんが、まだ発見されています。左外結合とは、左のテーブルのすべてのレコードを見つけることを指します。
ここにフェッチせずに状況については話しません。
3)次に、右の外側の結合を見てみましょう。名前から判断すると、それは左外の結合に関連している必要があります。例を直接見ることで、はっきりと見ることができます。
TUSER USR右外側の結合FETCH USR.ADDRESSESから
私たちはそれを実行し、hibernateから結果ステートメント出力を取得します:
hibernate:id1_0_としてtuser0_.idを選択し、addresses1_.idはid0_1_、tuser0_.name as name1_0_、tuser0_.age as age1_0_、address0_1_、address0_1_、address1_.user_id as user3_0_0_1_ t_addressアドレス1_ on tuser0_.id = addresses1_.user_idMySQLで実行した後の結果を見ることができます。
ここでは、アドレスがtest4であり、対応するユーザーがそれに対応するユーザーを持っていないことがわかりますが、それでもまだわかります。右外の結合とは、右のテーブルのすべてのレコードを見つけることを指します。
フェッチの状況は上記のとおりです。わからない場合は、Inner Join Fetchをご覧ください。