Ich habe kürzlich die benutzerdefinierte Art von Winterschlaf gesehen. Ich war noch nie zuvor ausgesetzt. Ich werde es hier als Konsolidierung meines Wissens aufzeichnen und Freunde, die noch nie ausgesetzt waren, um es gemeinsam zu lernen und zu studieren.
1) Benutzerdefinierte Typen, wie der Name schon sagt, sind natürlich Kursarten, die von sich selbst implementiert werden, da die internen Typen den Anforderungen nicht entsprechen. Es gibt nicht viele solcher Situationen, aber wir müssen es immer noch lernen. Wenn wir mehr Fähigkeiten haben, werden wir unseren Körper nicht unterdrücken. Erfahren Sie auch, wie andere überlegen, wie Sie beim Erstellen von Frameworks über Erweiterbarkeit nachdenken können.
Es gibt zwei Möglichkeiten, benutzerdefinierte Typen zu implementieren. Einer besteht darin, UserType zu implementieren, der andere besteht darin, CompositeSerType zu implementieren, und es gibt möglicherweise einige Methoden, aber ich habe es vorerst nicht verwendet, daher werde ich vorerst nicht darüber sprechen.
Ich verwende nur noch UserType. Schauen wir uns zunächst die Definition der Benutzeroberfläche an:
public interface userType { /*** Gibt die SQL -Typcodes für die von diesem Typ abgebildeten Spalten zurück. Die * Codes sind auf <tt> java.sql.types </tt> definiert. */ public int [] SQLTYPES (); /*** Die Klasse wurde von <Tt> nullSafetget () </tt> zurückgegeben. */ öffentliche Klasse returnedClass (); /*** Vergleichen Sie zwei Instanzen der Klasse, die von dieser Art für die Persistenz "Gleichheit" zugeordnet ist. * Gleichheit des anhaltenden Zustands. */ public boolean gleich (Objekt X, Objekt y) löst HibernateException aus; / ** * Holen Sie sich einen HashCode für die Instanz, die mit der Persistenz "Gleichheit" übereinstimmt. /*** Rufen Sie eine Instanz der kartierten Klasse von einem JDBC -Ergebnis ab. Implementierer * sollten die Möglichkeit von Nullwerten bewältigen. */ Public Object NullSafetget (Ergebnisset RS, String [] Namen, Objektbesitzer) löst HibernateException, SQLEXception aus; /*** Schreiben Sie eine Instanz der kartierten Klasse in eine vorbereitete Aussage. Implementierer * sollten die Möglichkeit von Nullwerten bewältigen. Ein Multi-Säulen-Typ sollte * in Parameter ab <Tt> Index </tt> geschrieben werden. */ public void nullsafeset (preparedStatement ST, Objektwert, int Index) löst HibernateException, SQLEXception aus; /** * Geben Sie eine tiefe Kopie des persistenten Staates zurück und halten Sie bei Einheiten und bei * Sammlungen an. Es ist nicht erforderlich, unveränderliche Objekte oder Null * -Werte zu kopieren. In diesem Fall ist es sicher, das Argument einfach zurückzugeben. */ Public Object DeepCopy (Objektwert) löst HibernateException aus; /*** Sind Objekte dieses Typs veränderlich? * * @return boolean */ public boolean ismutable (); /*** Verwandeln Sie das Objekt in seine zwischengespeicherbare Darstellung. Zumindest sollte diese * Methode eine tiefe Kopie ausführen, wenn der Typ veränderlich ist. Dies kann jedoch für einige Implementierungen nicht ausreichen; Beispielsweise müssen Assoziationen als * Bezeichnerwerte zwischengespeichert werden. (optionaler Betrieb) * * @param Wert Das zu zwischengeführte Objekt * @return Eine zwischengespeicherbare Darstellung des Objekts * @Throws HibernateException */ Public Serializable Disassemble (Objektwert) löst HibernateException aus; /*** rekonstruieren ein Objekt aus der zwischengespeicherbaren Darstellung. Zumindest sollte diese * Methode eine tiefe Kopie ausführen, wenn der Typ veränderlich ist. (optionaler Betrieb) */ öffentliches Objekt Montage (serialisierbarer Zwischenbetrieb, Objektbesitzer) wirft HibernateException aus; /** * Ersetzen Sie während der Zusammenführung den vorhandenen (Ziel-) Wert in der Entität, die wir mit einem neuen (ursprünglichen) Wert aus der abgelösten Entität verschmolzen, die wir verschmelzen. Für unveränderliche * Objekte oder Nullwerte ist es sicher, einfach den ersten Parameter zurückzugeben. Für * veränderliche Objekte ist es sicher, eine Kopie des ersten Parameters zurückzugeben. Für Objekte * mit Komponentenwerten kann es sinnvoll sein, die Komponentenwerte rekursiv zu ersetzen. */ öffentliches Objekt Ersetzen (Objekt Original, Objektziel, Objektbesitzer) löst HibernateException aus; } Tatsächlich können Sie es im Allgemeinen auf Englisch verstehen, daher werde ich es nicht mehr erklären. Hier sind wir die Hauptsache, die NullSafeset () -Methode implementieren. Diese Methode speichert hauptsächlich diese Art von Wert in der Datenbank. Dieses Mal lernen wir zuerst, wie man es benutzt, und dann werden wir langsam untersuchen, wie es intern implementiert wird.
2) Die Beispiele, die ich beim Studium geschrieben habe, bezogen sich auf das Beispiel von Xia Xins. Es ist also definitiv das gleiche wie die meisten Online. Lassen Sie es uns einfach ungefähr analysieren:
Unten finden Sie die Benutzerklasse
Paket org.hiberNate.Tutorial.Domain; importieren java.io.serializable; importieren java.util.list; Benutzer der öffentlichen Klasse implementiert serialisierbare {public Long ID; privater Zeichenfolge Name; private List -E -Mails; Verlassen Sie die GET/SET -Methode} Als nächstes kommt die benutzerdefinierte Emaillist -Klasse:
Paket org.hiberNate.Tutorial.Domain; importieren java.io.serializable; importieren java.sql.preeParedStatement; importieren java.sql.resultset; importieren java.sql.sqlexception; importieren java.sql.sql.types; Import Java.util.ArrayList; importieren java.util.list; import org.hiNNate.hiberNate; import org.hibernate.hibernateException; import org.hibernate.usertype.usertype; Public Class Emaillist implementiert Usertype {private statische endgültige Zeichen splitter = ';; private statische endgültige int [] type = new int [] {Typen.Varchar}; private String Assemble (Liste Emaillist) {StringBuilder strbuf = new StringBuilder (); für (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)); Listen emaillist = new ArrayList (); für (int i = 0; i <strsgth; i ++) {emaillist.add (strs [i]); } Return Emaillist; } public Object DeepCopy (Objektwert) löst HibernateException aus {list Sourzelist = (Liste) Wert; List targetList = new ArrayList (); targetList.add (Quellist); TargetList zurückgeben; } public serialisierbarer Disassemble (Objektwert) löst HibernateException aus {return null; } public boolean gleich (Objekt X, Objekt y) löst HibernateException aus {if (x == y) return true; System.out.println ("x:"+x+"y:"+y); if (x! = null && y! = null) {list xlist = (list) x; Liste ylist = (Liste) y; if (xlist.size ()! = ylist.size ()) return false; für (int i = 0; i <xlist.size (); i ++) {string str1 = (string) xlist.get (i); String str2 = (String) ylist.get (i); if (! str1.equals (str2)) return falsch; } Return true; } return false; } public boolean ismutable () {return false; } public Object nullSafetget (Ergebnisset rs, String [] Namen, Objektbesitzer) löst HibernateException, SQLEXception {String value = (String) hibernate.string.nullSafeget (rs, Namen [0]) aus; if (value! split} else {return null; }} public void nullSafeset (vorbereitete Statement ST, Objektwert, int Index) löscht HibernateException, SQLEXception {System.out.println ("Set -Methode ausgeführt!"); System.out.println ("Wert:" + Wert); if (value! Splice Hibernate.String.nullSafeset (ST, Str, Index); } else {hibernate.string.nullSafeset (ST, Wert, Index); }} öffentliche Klasse returnedClass () {return list.class; } public int [] SQLTYPES () {Return -Typen; } // andere Methoden weglassen, für die keine Änderung erforderlich ist} Die in der Klasse implementierten Methoden sind Methoden, die geändert werden müssen, und andere Methoden, die vorerst nicht geändert werden müssen, müssen nicht ausgeschrieben, aber sie müssen noch implementiert werden.
3) Als nächstes kommt die Zuordnungsdatei der Benutzerklasse:
<class name = "user" table = "user"> <id name = "id" column = "user_id" type = "java.lang.long"> <generator/> </id> <Eigenschaft name = "name" type = "String" column = "user_name"/> <Property name = "E -Mails" type.hibernate.tut.
Ich glaube, jeder weiß, wie man es modifiziert, und ich werde es hier nicht erklären. Es ändert hauptsächlich die Art der E -Mails und ändert sie in die gerade definierte Emaillist -Klasse.
4) Schließlich schreiben wir eine Testklasse:
import Java.util.hashMap; importieren java.util.list; import Java.util.map; Import Java.util.ArrayList; Import JUNIT.Framework.TestCase; import org.hiberNate.entityMode; import org.hibernate.session; import org.hiberNate.sessionFactory; import org.hibernate.transaction; import org.hibernate.cfg.configuration; import org.hibernate.tutorial.domain.user; public class hibernatetest erweitert testCase {private sitzung = null; Protected void setup () löst Ausnahme aus {Konfiguration cfg = new Configuration (). configure (); SessionFactory SessionFactory = cfg.buildSessionFactory (); Session = SessionFactory.openSession (); } public void TestInsert () {Transaktion tran = null; try {tran = session.beginTransaction (); User user = new user (); user.setName ("Shun"); Listlist = new ArrayList (); list.add ("[email protected]"); list.add ("[email protected]"); user.setemails (Liste); Session.save (Benutzer); tran.commit (); } catch (Ausnahme ex) {ex.printstacktrace (); if (tran! = null) {tran.rollback (); }} protected void reaNdown () löst eine Ausnahme aus {session.close (); }} Hier kann es ein Problem geben. Wenn wir nur eine E -Mail speichern, wird sie eine Ausnahme haben. Das E -Mail -Feld in der Datenbank ist leer. Wenn wir zwei Codes wie den obigen Code haben, wird es kein Problem geben. Das Ergebnis in der Datenbank ist wie in der Abbildung gezeigt:
Und wenn wir nur einen speichern, lautet die Ausnahme wie folgt:
java.lang.classcastexception: java.util.arrayList kann nicht an java.lang.string übertragen werden
Es tritt in der Equals -Methode von Emaillist auf, string str1 = (String) xlist.get (i); In diesem Code wird nach der Überprüfung eine Liste der Liste, wenn Daten eingefügt und an die NullSafeset -Methode von Emaillist weitergegeben werden.
Wert: [[[email protected], [email protected]]] Dieses Formular verursacht beim Vergleich Probleme. Es hat immer nur einen Wert, ist aber beim Vergleich anders.
if (xlist.size ()! = ylist.size ()) return false;
Es wird also Probleme beim Casting geben.
Nach der Inspektion die gleiche Methode:
X: [[[email protected], [email protected]]] Y: [[email protected], [email protected]]
Dieses Ergebnis ist sehr seltsam. Das Internet sprach nicht darüber, warum diese Situation aufgetreten ist. Lassen Sie es mich hier vorschlagen: Die Hibernate -Version, die ich verwende, ist Hibernate 3.3.2.ga. Ich weiß nicht, ob es sich um ein Versionsproblem oder ein anderes Problem handelt. Lassen Sie es uns morgen studieren. Wenn jemand weiß, warum, hoffe ich, dass ich es mir sagen werde.