私は最近、冬眠のカスタムタイプを見ました。私はそれにさらされたことがありません。ここでは、私の知識の統合としてここで録音し、それを学び、研究するために一度もさらされたことのない友人にさせます。
1)名前が示すように、カスタムタイプは、もちろん、内部タイプがニーズを満たしていないため、それ自体で実装されるタイプです。そのような状況は多くありませんが、それでも学ぶ必要があります。より多くのスキルがあれば、体を抑制しません。また、フレームワークを作成する際に、他の人が拡張性について考える方法をどのように検討するかを学びます。
カスタムタイプを実装するには2つの方法があります。1つはusertypeを実装することです。もう1つはcompositeusertypeを実装することです。また、いくつかの方法があるかもしれませんが、当面は使用していないので、今のところは話しません。
当面はUserTypeのみを使用しています。まず、USERTYPEインターフェイスの定義を見てみましょう。
パブリックインターフェイスusertype { /***このタイプでマッピングされた列のSQLタイプコードを返します。 *コードは<tt> java.sql.types </tt>で定義されています。 */ public int [] sqltypes(); /*** <tt> nullsafeget()</tt>によって返されたクラス。 */ public class returnedclass(); /***このタイプでマッピングされたクラスの2つのインスタンスを、持続性「平等」のために比較します。 *永続的な状態の平等。 */ public boolean Equals(オブジェクトx、オブジェクトy)は冬眠exceptionをスローします。 / ** *インスタンスのハッシュコードを取得します。これは、持続性「等式」と一致しています */ public int hashcode(object x)はhibernateexceptionをスローします。 /*** JDBC結果からマッピングされたクラスのインスタンスを取得します。実装者 *は、ヌル値の可能性を処理する必要があります。 */ public Object nullsafeget(resultset rs、string [] names、object ofbent offern)hibernateexception、sqlexception; /***マッピングされたクラスのインスタンスを準備したステートメントに書き込みます。実装者 *は、ヌル値の可能性を処理する必要があります。 <tt> index </tt>から始まるパラメーターにマルチコラムタイプを記述する必要があります。 */ public void nullsafeset(preatedStatement ST、Object Value、int Index)STHRE hibernateException、sqlexception; /** *永続的な状態の深いコピーを返し、エンティティと *コレクションで停止します。不変のオブジェクトまたはnull *値をコピーする必要はありません。その場合、引数を単純に返すことは安全です。 */ public Object deepcopy(オブジェクト値)はhibernateExceptionをスローします。 /***このタイプのオブジェクトは可変ですか? * * @return boolean */ public boolean ismutable(); /***オブジェクトをキャッシュ可能な表現に変換します。少なくとも、この *メソッドは、タイプが可変である場合、深いコピーを実行する必要があります。ただし、一部の実装では十分ではない場合があります。たとえば、アソシエーションは *識別子値としてキャッシュする必要があります。 (オプションの操作) * * @param値オブジェクトはキャッシュされます/***キャッシュ可能な表現からオブジェクトを再構築します。少なくとも、この *メソッドは、タイプが可変である場合、深いコピーを実行する必要があります。 (オプションの操作) */パブリックオブジェクトアセンブル(シリアル化可能なキャッシュ、オブジェクトの所有者)は、HibernateExceptionをスローします。 /** *マージ中に、マージされたエンティティの既存の(ターゲット)値を、マージしている分離したエンティティの新しい(元の)値と交換します。不変の *オブジェクト、またはnull値の場合、最初のパラメーターを単純に返すだけで安全です。 *可変オブジェクトの場合、最初のパラメーターのコピーを返すことは安全です。コンポーネント値を持つオブジェクト *の場合、コンポーネント値を再帰的に置き換えることが理にかなっている場合があります。 */パブリックオブジェクトの交換(オブジェクトオリジナル、オブジェクトターゲット、オブジェクト所有者)は、hibernateExceptionをスローします。 }実際、一般的に英語で理解できるので、これ以上説明しません。ここでは、nullSafeset()メソッドを実装する主なことです。この方法は、主にこのタイプの値をデータベースに保存することを使用しています。今回は、最初にそれを使用する方法を学び、次に内部でどのように実装されるかをゆっくりと研究します。
2)私が勉強していたときに書いた例は、Xia Xinの例を参照していたので、それは間違いなくほとんどのオンラインの例と同じです。大まかに分析しましょう:
以下はユーザークラスです
パッケージorg.hibernate.tutorial.domain; java.io.serializableをインポートします。 java.util.listをインポートします。パブリッククラスのユーザーはSerializable {public long id;プライベート文字列名;プライベートリストメール; get/setメソッドを省略}次はカスタムエマイリストクラスです。
パッケージorg.hibernate.tutorial.domain; java.io.serializableをインポートします。 Java.sql.preparedStatementをインポートします。 java.sql.resultsetをインポートします。 java.sql.sqlexceptionをインポートします。 java.sql.sql.typesをインポートします。 java.util.arraylistをインポートします。 java.util.listをインポートします。 org.hibernate.hibernateをインポートします。 org.hibernate.hibernateExceptionをインポートします。 org.hibernate.usertype.usertypeをインポートします。パブリッククラスのemaillistはusertypeを実装します{private static final char splitter = ';'; private static final int [] Types = new int [] {types.Varchar}; private string assemble(list emaillist){stringbuilder strbuf = new StringBuilder(); for(int i = 0; i <emaillist.size() - 1; i ++){strbuf.append(emaillist.get(i))。append(splitter); } strbuf.append(emaillist.get(emaillist.size() - 1)); return strbuf.toString(); } private list parse(string value){string [] strs = org.hibernate.util.stringhelper.split(value、string.valueof(splitter));リストemaillist = new ArrayList(); for(int i = 0; i <strs.length; i ++){emaillist.add(strs [i]); } emaillistを返します。 } public object deepcopy(object value)hibernateexception {list sourcelist =(list)value; List TargetList = new ArrayList(); TargetList.Add(Sourcelist);ターゲットリストを返します。 } public Serializable Resosemble(オブジェクト値)hibernateException {return null; } public boolean equals(オブジェクトx、オブジェクトy)hibernateexception {if(x == y)return true; System.out.println( "x:"+x+"y:"+y); if(x!= null && y!= null){list xlist =(list)x;リストylist =(list)y; if(xlist.size()!= ylist.size())return false; for(int i = 0; i <xlist.size(); i ++){string str1 =(string)xlist.get(i); string str2 =(string)ylist.get(i); if(!str1.equals(str2))falseを返します。 } trueを返します。 } falseを返します。 } public boolean isMutable(){return false; } public Object nullSafeget(resultset rs、string [] names [] names、object object ofbent object object exception、sqlexception {string value =(string)hibernate.string.nullsafeget(rs、names [0]); if(value!= null){parse(value); //貼り付けリスト; split} else {return null; }} public void nullsafeset(preatedstatement st、object value、int index)hibernateexception、sqlexception {system.out.println( "set method exected!"); System.out.println( "value:" + value); if(value!= null){string str = assemble((list)value); //文字列を使用; Splice hibernate.string.nullsafeset(st、str、index); } else {hibernate.string.nullsafeset(st、value、index); }} public class returnedclass(){return list.class; } public int [] sqltypes(){return types; } //変更を必要としない他の方法を省略します}クラスで実装されている方法は、変更する必要がある方法であり、当面は変更されていない他のメソッドですが、作成する必要がありますが、実装する必要があります。
3)次は、ユーザークラスのマッピングファイルです。
<class name = "user" table = "user"> <id name = "id" column = "user_id" type = "java.lang.long"> <generator/> </id> <プロパティ名= "name" type = "string" column "/> <プロパティ名=" emails "type =" org.hibernate.tutorial。
私は誰もがそれを変更する方法を知っていると信じています、そして私はここでそれを説明しません。それは主に電子メールの種類を変更し、それを私たちが定義したばかりのエマイリストクラスに変更します。
4)最後に、テストクラスを書きましょう。
java.util.hashmapをインポートします。 java.util.listをインポートします。 java.util.mapをインポートします。 java.util.arraylistをインポートします。 junit.framework.testcaseをインポートします。 import org.hibernate.entityMode; org.hibernate.sessionをインポートします。 Import org.hibernate.sessionFactory; org.hibernate.transactionをインポートします。 Import org.hibernate.cfg.configuration; Intorg org.hibernate.tutorial.domain.user; Public Class HibernatetestはTestCaseを拡張します{プライベートセッションセッション= null;保護されたvoid setup()throws exception {configuration cfg = new Configuration()。configure(); SessionFactory SessionFactory = CFG.BuildSessionFactory(); session = sessionfactory.opensession(); } public void testinsert(){transaction tran = null; try {tran = session.begintransaction(); user user = new user(); user.setname( "shun");リストリスト= new arrayList(); list.add( "[email protected]"); list.add( "[email protected]"); user.setemails(list); session.save(user); tran.commit(); } catch(Exception ex){ex.printstacktrace(); if(tran!= null){tran.rollback(); }}保護されたvoid teardown()throws exception {session.close(); }}ここに問題があるかもしれません。電子メールを1つだけ保存すると、例外があります。データベースの電子メールフィールドは空です。上記のコードのような2つのコードがある場合、問題はありません。データベースの結果は、図に示されているとおりです。
そして、1つだけを保存する場合、例外は次のとおりです。
java.lang.classcastexception:java.util.arraylistはjava.lang.stringにキャストできません
それは、emaillistの等しい方法で発生します、string str1 =(string)xlist.get(i);このコードでは、チェックした後、データを挿入してemaillistのnullsafesetメソッドに渡す際のリストのリストになります。
値:[[[email protected]、[email protected]]]]このフォームは、比較時に問題を引き起こします。常に1つの値しかありませんが、比較すると異なります。
if(xlist.size()!= ylist.size())return false;
したがって、キャストする際に問題が発生します。
検査後、等しい方法:
X:[[[email protected]、[email protected]]] Y:[[email protected]、[email protected]]
この結果は非常に奇妙です。インターネットは、なぜこの状況が起こったのかについては話しませんでした。ここで提案しましょう:私が使用している冬眠版は冬眠3.3.2.gaです。それがバージョンの問題なのか別の問題なのかはわかりません。明日勉強しましょう。誰かが理由を知っているなら、私は私に教えてくれることを願っています。