インターセプター
インターセプターといえば、Struts2に精通している子供用の靴は間違いなくStruts2に精通していると思います。 Struts2は、インターセプターをカスタマイズして、必要な一連の関連作業を実行できます。そして、ここで話しているインターセプターには、同様の機能もあります。
ナンセンスを言わずに、コードだけです:
以下は、インターセプターインターフェイスを実装するMyInterceptorクラスです。
public string onpreparestatement(string arg0){return arg0; } public boolean onsave(object arg0、serializable arg1、object arg2、string [] arg3、type [] arg4)callbackexception {if(arg0 instanceof user){system.out.println( "save =>"+"+(user)arg0).getName()); } falseを返します。 }他の方法は読みません。デフォルトの実装に従ってください。これら2つの方法を変更するだけです。現在のSQLステートメントを返すには、即席の返品値を変更する必要があります。パラメーターは、実行されたSQLステートメントが渡されたものです。直接返送してステートメントを印刷できます。
Onsaveでは、保存時に呼び出されることがわかります。一連の事前保存作業を行うことができます。
パラメーター名を見ることで誰もがそれを理解できると思います。
Serializableは、シーケンス番号のパラメーターを指します。これは、データベースIDにマップされる属性を指します。
オブジェクト[]これは一連の状態であり、当面はあまり使用されていません。後で勉強します。ただし、APIは、この配列の値がどのように変更されても、OnSaveメソッドがtrueを返す必要があることを説明しています。
文字列[]は属性の名前を指し、型[]は対応する属性のタイプです。
1)このインターセプターは、データベースを保存する前後に対応する操作を行うことができます。たとえば、データを変更してプレフィックスまたはサフィックスを追加する場合は、それを使用して実装できます。以下で見てみましょう。
public boolean onsave(object arg0、serializable arg1、object [] arg2、string [] arg3、type [] arg4)throws callbackexception {if(arg0 instanceof user){system.out.println( "保存=>"+((user)arg0).getname()); } //ここで名前の接頭辞として123を追加しますuser users user =(user)arg0; user.setName( "123"+user.getName()); falseを返します。 }テスト方法を見てみましょう。
public static void main(string [] args){configuration cfg = new configuration()。configure(); SessionFactory SessionFactory = CFG.BuildSessionFactory();インターセプターインターセプター= new MyInteceptor();セッションセッション= sessionfactory.opensession(interceptor); user user = new user(); user.setname( "shun");トランザクションtx = session.begintransaction(); session.save(user); tx.commit(); session.close(); }それは非常に簡単です、私たちはそれを単純に保存しました。ここにマッピングファイルやエンティティクラスはありません。試してみてください。
それを実行すると、私たちは見ることができます:
保存するユーザー=> shun hibernate:inserting into user(user_name、age)values(?、?)hibernate:uspetwed user set user_name =?、age =? user_id =?主にOnSaveメソッドを変更したため、最後に名前と年齢を更新します。
public boolean onload(object arg0、serializable arg1、object [] arg2、string [] arg3、type [] arg4)throws callbackexception {if(arg0 instanceof user){system.out.println( "loaded =>"+(arg2 [0]+":"+arg2 [1]); } user user =(user)arg0; //(int i = 0; i <arg3.length; i ++){if(arg3 [i] .equals( "name")){user.setname((string)arg2 [i])。置換( "123"、 "")) arg2 [i] =((string)arg2 [i])。置換( "123"、 ""); }} falseを返します。 }読み込み時の変更された属性の値は、オンロード方法で記述されます。
ここのArg0はユーザーオブジェクトです。まだ価値がありません。この方法はロードメソッドの後に呼び出されるため、現時点でユーザーを操作することは役に立たず、ユーザー.setNameは役に立たない操作です。主に:
arg2 [i] =((string)arg2 [i])。置換( "123"、 "");
このコードは、返された属性の値を変更するため、プログラムで取得するユーザーオブジェクトの値も変更されます。表示するテスト方法を実行しましょう。
public static void main(string [] args){configuration cfg = new configuration()。configure(); SessionFactory SessionFactory = CFG.BuildSessionFactory();インターセプターインターセプター= new MyInteceptor();セッションセッション= sessionfactory.opensession(interceptor);ユーザーユーザー=(user)session.load(user.class、new long(39)); System.out.println( "user name:"+user.getName()); session.close(); }結果を見て、私たちは次のようにしました:
hibernate:user1_0_0_、user0.user_nameとしてuser2_0_0_、user0.user_id = aseg0_0_としてuser2_0_0_、user2_0_0_としてuser2_0_0_としてuser0_.user_nameを選択します。ロードされるユーザー=> 123shun:0ユーザー名:shun
元の123を削除し、実際の荷重後に関連する処理を実行しましたが、これは実際のロード前の実際の処理ではなく、推測を少し疑っています。しかし、それも考慮事項です。インターセプターは、ログの関連する処理で最も使用できます。たとえば、操作ごとに対応してログインする必要があるため、インターセプターが適切な選択です。
コレクション
前の例で1対多で使用したセットを覚えていますが、あなたはまだ印象を持っていますか?そうでない場合は、情報を確認して確認してください。今日は、これらのコレクションについて学びます。
ポイントに到達しましょう。
1)最初にセットを学びましょう。 Java Utilパッケージにセットもあることを誰もが知っています。では、冬眠中のセットとセットの違いとつながりは何ですか? Hibernate APIを開き、セットを見つけて、それを見ることができます。
私たちが見るのは、そのような冬眠コレクションの親クラスです。一連の具体的な実装クラスを備えた抽象クラスです。次の方法を見続けると、このクラスがJavaコレクションのカプセル化を実装していることがわかります。そのため、いわゆる冬眠セットは実際にJavaセットのみをカプセル化することを理解しています。
それで、この特性は、冬眠のセットの重複要素を許可しないものですか?答えはもちろんそうです。
ここではこれらを見ていません。過去には、マッピングを学んだとき、プロパティを関連するクラスと直接関連付けましたが、今日はこのようなものではありません。別の方法を使用して、文字列を関連付けて問題があるかどうかを確認します。
しかし、この質問を見る前に、Javaの文字列比較を見てみましょう。
私たちが見るのは、そのような冬眠コレクションの親クラスです。一連の具体的な実装クラスを備えた抽象クラスです。次の方法を見続けると、このクラスがJavaコレクションのカプセル化を実装していることがわかります。そのため、いわゆる冬眠セットは実際にJavaセットのみをカプセル化することを理解しています。
それで、この特性は、冬眠のセットの重複要素を許可しないものですか?答えはもちろんそうです。
ここではこれらを見ていません。過去には、マッピングを学んだとき、プロパティを関連するクラスと直接関連付けましたが、今日はこのようなものではありません。別の方法を使用して、文字列を関連付けて問題があるかどうかを確認します。
しかし、この質問を見る前に、Javaの文字列比較を見てみましょう。
public static void main(string [] args){string s1 = "shun1";文字列s2 = "shun1"; System.out.println( "s1 == s2:"+(s1 == s2)); }多くの子供たちの靴は答えが真実であることを知っていると思います。
例を挙げる前に、マッピングファイルを見てみましょう。マッピングクラスは書きません。
これは、Tuserのマッピングファイルです。
<class name = "tuser" table = "t_user" dynamic-insert = "true" dynamic-update = "true" dynamic-update = "true"> <id name = "id" id "column =" id "> <generator/> </id> <プロパティ名=" name "type =" java.lang.string "column =" "type =" "" java.列= "age"/> <set name = "addresses" cascade = "all" table = "t_address"> <key column = "user_id"/> <! - <on-many/> - > <element column = "address" type = "string"/> </set> </class>
次はアドレスマッピングファイルです。
<class name = "address" table = "t_address" dynamic-insert = "false" dynamic-update = "false"> <id name = "id" column = "id" type = "java.lang.integer"> < /id> <プロパティname = "アドレス"列= "アドレス" type = "java.lang.string" /string "colum" colum one = "colum name not-null = "true"> </muly-one> </class>
子供の靴はそれをはっきりと見てきました。 Tuserのセットで1対Manyをコメントし、Elementを使用しました。問題が何であれ、最初にデータベースを見てみましょう。
これはT_Addressテーブルです:
これがT_USERテーブルです:
ID 4のユーザーが3つのアドレスに対応していることがわかります。次に、テスト方法を見てみましょう。
public static void main(string [] args){configuration cfg = new configuration()。configure(); SessionFactory SessionFactory = CFG.BuildSessionFactory();セッションセッション= sessionfactory.opensession(); tuser user =(tuser)session.load(tuser.class、new Integer(4)); set set = user.getAddresses(); session.close(); System.out.println( "アドレスサイズ:"+set.size()); }非常にシンプルなクエリクラス、この結果を取り出したばかりで、奇妙な現象を見ました。
アドレスサイズ:1
これが結果です!
あなたは間違いなく言うでしょう、それは間違っているに違いありません、それは冬眠のバグです。私はここで幸せでなければなりません。ついにバグを送信できます。仕事を切り替えたとき、私は冬眠のバグを提出したと大声で言うことができました。ハハ、しかし残念ながら、これはバグではありません。
私たちが前に持っていた文字列の比較がここに道を舗装しているので、それを舗装する方法は?
構成ファイルでセットを使用し、文字列文字を介して関連付けます。次に、データベースで取り出されてセットに入れられると、関連する文字の値が等しいかどうかを最初に決定します。ここで、私たちの値は等しいので(当面の間比較することはありません)、文字列を使用して比較するときに、Javaの弦トラップに再び陥ることを知る必要があります。 1つしかないことがわかった場合、削除を削除すると削除が面倒になります。同じレコードをすべて削除します。
次に、削除されたものを見てみましょう。
tuser user =(tuser)session.load(tuser.class、new Integer(4));トランザクションtx = session.begintransaction();オブジェクトobj = user.getAddresses()。iterator()。next(); user.getAddresses()。remove(obj); tx.commit(); session.close();
ここの冬眠による声明出力は次のとおりです。
hibernate:user_id =?
ユーザーの下のすべてのアドレスを削除することを誰もが知っていると思います。これらすべてを削除する以外に選択肢はありません。
したがって、実際の開発でそれに注意を払う必要があります。
2)上記のセットについて話しましたが、使用するのはそれほど快適ではないようです。そのようなトラップがありますが、方法はありません。セットは私たちが最も使用するものであり、一般に誰も直接文字列を関連付けることはありません。しかし、多くの人々はまだ不幸なので、冬眠は必要に応じて余分なバッグを持っています(おそらく必要ではないかもしれません。
まず、その基本的な使用法を見てみましょう。
まず、前のTuserマッピングファイルのセットタグを次のように変更する必要があります。
<bag name = "アドレス" lazy = "true" table = "t_address"> <key column = "user_id" /> <要素タイプ= "文字列"列= "アドレス" /> < /bag>
また、対応するエンティティクラスは、リストタイプにアドレスタイプを変更する必要があります。
ここでは、3つのアドレスを追加します。
テストコードを実行します。
public static void main(string [] args){configuration cfg = new configuration()。configure(); SessionFactory SessionFactory = CFG.BuildSessionFactory();セッションセッション= sessionfactory.opensession(); tuser user =(tuser)session.load(tuser.class、new Integer(4)); system.out.println( "アドレスサイズ:"+user.getAddresses()。size()); session.close(); }
ここにわかります:
アドレスサイズ:3
今回は、繰り返しがあるかどうかに関係なく、すべてを見ることができます。
しかし、削除の問題を見ただけです。ここではバッグが解決されていないため、idbagを使用する必要があります。構成ファイルが表示され、次の変更が必要です。
idbag name = "addresses" table = "t_address" lazy = "true"> <collection-id type = "int" column = "id"> <generator /> < /collection-id> <key column = "user_id" /> <要素タイプ= "文字列"列= "アドレス" /> < /idbag>
削除するレコード番号を示すために、バッグよりも1つのコレクションIDしかないことがわかります。
削除されたコードを再実行したとき:
tuser user =(tuser)session.load(tuser.class、new Integer(4));トランザクションtx = session.begintransaction();オブジェクトobj = user.getAddresses()。iterator()。next(); user.getAddresses()。remove(obj); tx.commit();
出力ステートメントは次のとおりです。
hibernate:t_addressから削除where id =?
今回は、user_idを介して削除されるのではなく、t_addressのIDに基づいて削除されます。つまり、削除する必要があるレコードを本当に削除します。
データベースが表示され、レコードは次のとおりです。
最初のレコードを削除しましたが、それは正しいです。
3)上記の2つの方法を見た後、マップを見てみましょう。それと上記の2つの最大の違いは、キー値に対応できることです。直感的な視点を直接見る:
まず、構成ファイルを変更する必要があります。
<Map name = "アドレス" table = "t_address" lazy = "true"> <key column = "user_id" /> <index type = "string" column = "type" /> <要素タイプ= "string" column = "address" /> < /map>
それと前の2つの最大の違いは、Javaのマップキーに相当するインデックスがあることです。これを使用して対応するレコードを取得します。ここで変更した後、対応するエンティティクラスを変更する必要があることを忘れないでください。また、アドレスの属性のタイプをMAPに変更する必要があります。
データベースデータをご覧ください。
ここでは、2つのオフィスと1つの家があることがわかります。どのオフィスを使用する必要がありますか?
心配しないでください、私たちはテストコードを実行した後に知っています:
tuser user =(tuser)session.load(tuser.class、new Integer(4)); System.out.println(user.getAddresses()。get( "home")); system.out.println(user.getAddresses()。get( "office"));
シャンウェイ上海
はい、結果が示すように、マップの原理と同じです。保存された値は、以前の値を上書きします(それらが同じキーの場合)。
マップは比較的単純で、最初の2つに匹敵します。
4)最後のものを見てみましょう。リストは以前のものとは異なり、ソートすることができます。
それがどのように実装されているかを見てみましょう:
まず、マッピングファイルを変更しましょう。
<リストname = "アドレス" table = "t_address" lazy = "true"> <key column = "user_id" /> <index type = "string" column = "idx" /> <element type = "string" column = "address" /> < /list>
マップの構成に似ていますが、インデックスの属性は異なります。マップ内のインデックスは、値を取得するためのキーとして使用され、リストのインデックスはソートとして使用されます。
データベースを見てみましょう:
0、1、および2の順序で3つの値を設定します。
コードを実行して、0と2の値を変更しましょう。
tuser user =(tuser)session.load(tuser.class、new Integer(4));トランザクションtx = session.begintransaction();オブジェクトobj1 = user.getAddresses()。get(0);オブジェクトobj2 = user.getAddresses()。get(2); user.getAddresses()。set(0、obj2); user.getAddresses()。set(2、obj1); tx.commit();
結果が表示されます:
0と2が置き換えられていることがわかりますが、もちろんこれはIDXの値を変更しているだけです。しかし、これは基本的にソート機能を実装しています。