J'ai récemment vu le type personnalisé d'hibernate. Je n'y ai jamais été exposé auparavant. Je vais l'enregistrer ici comme une consolidation de mes connaissances et laisser des amis qui n'ont jamais été exposés à l'apprendre et à l'étudier ensemble.
1) Les types personnalisés, comme son nom l'indique, sont bien sûr des types qui sont implémentés par eux-mêmes parce que les types internes ne répondent pas aux besoins. Il n'y a pas beaucoup de ces situations, mais nous devons encore l'apprendre. Si nous avons plus de compétences, nous ne supprimerons pas notre corps. Apprenez également comment les autres considèrent comment penser à l'extensibilité lors de la fabrication de cadres.
Il existe deux façons d'implémenter des types personnalisés, l'un consiste à implémenter UserType, l'autre est d'implémenter CompositeUserType, et il peut y avoir des méthodes, mais je ne l'ai pas utilisée pour le moment, donc je n'en parlerai pas pour le moment.
J'utilise UserType uniquement pour le moment, examinons d'abord la définition de l'interface UserType:
Interface publique UserType {/ ** * Renvoie les codes de type SQL pour les colonnes mappées par ce type. Les * codes sont définis sur <TT> java.sql.types </tt>. * / public int [] sqlTypes (); / ** * La classe renvoyée par <TT> nullSaFangeget () </tt>. * / Classe publique RetournedClass (); / ** * Comparez deux instances de la classe mappée par ce type pour la persistance "égalité". * Égalité de l'état persistant. * / public boolean est égal (objet x, objet y) lève HiberNateException; / ** * Obtenez un code de hash pour l'instance, cohérent avec la persistance "Equalité" * / public int hashcode (objet x) lève HiberNateException; / ** * Récupérez une instance de la classe mappée à partir d'un résultat JDBC. Les implémentors * doivent gérer la possibilité de valeurs nulles. * / public Object NullSaFeget (ResultSet RS, String [] Noms, Oblinter Owners) lève HiberNateException, SQELPECTING; / ** * Écrivez une instance de la classe mappée à une instruction préparée. Les implémentors * doivent gérer la possibilité de valeurs nulles. Un type multi-colonne doit être écrit * aux paramètres à partir de <TT> index </TT>. * / public void nullsafeSet (préparéstatement st, objet Value, int index) lève HiberNateException, sqlexception; / ** * Renvoyez une copie profonde de l'état persistant, en s'arrêtant aux entités et aux * collections. Il n'est pas nécessaire de copier des objets immuables, ou des valeurs nuls *, auquel cas il est sûr de simplement renvoyer l'argument. * / Objet public DeepCopy (Valeur d'objet) lève HiberNateException; / ** * Les objets de ce type sont-ils mutables? * * @return boolean * / public boolean ismutable (); / ** * Transformez l'objet en sa représentation cacheable. À tout le moins, cette méthode * devrait effectuer une copie profonde si le type est mutable. Cependant, cela peut ne pas être suffisant * pour certaines implémentations; Par exemple, les associations doivent être mises en cache comme * valeurs d'identifiant. (Opération facultative) * * @param Valeur L'objet à mettre en cache * @return une représentation cacheable de l'objet * @throws HiberNateException * / public Serializable Disassemble (Valeur de l'objet) lève HiberNateException; / ** * Reconstruire un objet de la représentation cacheable. À tout le moins, cette méthode * devrait effectuer une copie profonde si le type est mutable. (opération facultative) * / Objet public Assemble (Serializable Cached, propriétaire d'objet) lève HiberNateException; / ** * Pendant la fusion, remplacez la valeur (cible) existante dans l'entité dans laquelle nous sommes fusionnés * par une nouvelle valeur (originale) de l'entité détachée que nous fusions. Pour les objets immuables * ou les valeurs nuls, il est sûr de renvoyer simplement le premier paramètre. Pour * les objets mutables, il est sûr de renvoyer une copie du premier paramètre. Pour les objets * avec des valeurs de composants, il peut être logique de remplacer récursivement les valeurs des composants. * / Public Object Remplace (objet Original, Target d'objet, propriétaire d'objet) lève HiberNateException; } En fait, vous pouvez le comprendre en anglais en général, donc je ne l'expliquerai pas davantage. Ici, la principale chose, nous sommes de mettre en œuvre la méthode nullsafeSet (). Cette méthode utilise principalement l'enregistrement de ce type de valeur dans la base de données. Cette fois, nous apprendrons à l'utiliser d'abord, puis nous étudierons lentement comment il est mis en œuvre en interne.
2) Les exemples que j'ai écrits lorsque j'étudiais faisait référence à l'exemple de Xia Xin, donc c'est certainement la même chose que la plupart des plus en ligne. Analyons-le grossièrement:
Ci-dessous est la classe d'utilisateurs
package org.hibernate.tutorial.domain; import java.io.serializable; Importer java.util.list; La classe publique utilisateur implémente Serializable {public long id; nom de chaîne privé; e-mails de liste privée; omettre la méthode de get / set} Ensuite, la classe Emaillist personnalisée:
package org.hibernate.tutorial.domain; import java.io.serializable; Importer java.sql.PreparedStatement; import java.sql.resultSet; import java.sql.sqlexception; Importer java.sql.sql.types; import java.util.arraylist; Importer java.util.list; import org.hibernate.hibernate; import org.hibernate.hibernateException; import org.hibernate.usertype.userType; La classe publique EmailList implémente UserType {private static final char Splitter = ';'; Final statique privé int [] types = new int [] {types.varchar}; Assemble de chaîne privée (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 (valeur, string.valueof (Splitter)); List emailList = new ArrayList (); for (int i = 0; i <str.length; i ++) {emaillist.add (strs [i]); } retour émaillist; } public Object DeepCopy (Valeur d'objet) lève HiberNateException {List SourceList = (List) Value; List cibleList = new ArrayList (); TargetList.add (SourceList); return TargetList; } public Serializable Disassemble (Valeur d'objet) lève HiberNateException {return null; } public booléen égaux (objet x, objet y) lève HiberNateException {if (x == y) return true; System.out.println ("x:" + x + "y:" + y); if (x! = null && y! = null) {list xlist = (list) x; List ylist = (list) y; if (xList.size ()! = ylist.size ()) return false; pour (int i = 0; i <xlist.size (); i ++) {String str1 = (string) xlist.get (i); String str2 = (String) yList.get (i); if (! str1.equals (str2)) renvoie false; } return true; } return false; } public boolean ismutable () {return false; } public Object NullSaFeget (ResultSet RS, String [] Noms, Oblinter Ownwear) lève HiberNateException, SQELLEXception {String Value = (String) HiberNate.String.NullsaFeget (rs, noms [0]); if (valeur! = null) {return parse (valeur); // coller la liste; Split} else {return null; }} public void nullSaFeSet (préparéStatement st, valeur objet, int index) lève HiberNateException, sqException {System.out.println ("Set Method Executed!"); System.out.println ("valeur:" + valeur); if (valeur! = null) {String str = asseble ((list) value); // utilise des chaînes; Splice Hibernate.String.NullsafeSet (St, Str, Index); } else {hibernate.string.nullsafeset (st, value, index); }} classe publique returnClass () {return list.class; } public int [] sqlTypes () {return types; } // omettre d'autres méthodes qui ne nécessitent pas de modification} Les méthodes implémentées dans la classe sont des méthodes qui doivent être modifiées, et d'autres méthodes qui n'ont pas besoin d'être modifiées pour le moment n'ont pas été écrites, mais elles doivent encore être implémentées.
3) Ensuite, le fichier de mappage de la classe utilisateur:
<class name = "user" table = "user"> <id name = "id" colonnen = "user_id" type = "java.lang.long"> <générateur /> </ id> <propriété name = "name" type = "string" column = "user_name" /> <property name = "e-mail" type = "org.hibernate.
Je crois que tout le monde sait comment le modifier, et je ne l'expliquerai pas ici. Il modifie principalement le type d'e-mails et le modifie dans la classe émailliste que nous venons de définir.
4) Enfin, écrivons une classe de test:
import java.util.hashmap; Importer java.util.list; importation java.util.map; import java.util.arraylist; Importer 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; classe publique HiberNateTest étend TestCase {Session Private Session Session = NULL; Protected void setup () lève une exception {configuration cfg = new Configuration (). configure (); SessionFactory SessionFactory = cfg.BuildSessionFactory (); session = sessionfactory.opencession (); } public void testiNsert () {transaction trans transfaste = null; essayez {trans-= session.begintransaction (); Utilisateur utilisateur = nouveau utilisateur (); user.setName ("shun"); List list = new ArrayList (); list.add ("[email protected]"); list.add ("[email protected]"); user.setEmails (liste); session.save (utilisateur); Tran.Commit (); } catch (exception ex) {ex.printStackTrace (); if (Tran! = null) {Tran.rollback (); }} Protected void Teardown () lève une exception {session.close (); }} Il peut y avoir un problème ici. Lorsque nous n'enregistrons qu'un seul e-mail, il aura une exception. Le champ de messagerie dans la base de données est vide. Lorsque nous avons deux codes comme le code ci-dessus, il n'y aura pas de problème. Le résultat dans la base de données est comme indiqué sur la figure:
Et lorsque nous n'en enregistrons qu'une, l'exception est la suivante:
java.lang.classCastException: java.util.arraylist ne peut pas être jeté sur java.lang.string
Il se produit dans la méthode equals d'Emaillist, String str1 = (String) xList.get (i); Dans ce code, après avoir vérifié, il devient une liste de liste lors de l'insertion de données et de la transmission à la méthode nullsafeset d'Emaillist, c'est-à-dire,
Valeur: [[[email protected], [email protected]]]] Ce formulaire causera des problèmes lors de la comparaison. Il n'a toujours qu'une seule valeur, mais elle est différente lors de la comparaison.
if (xList.size ()! = ylist.size ()) return false;
Il y aura donc des problèmes lors du casting.
Après inspection, la méthode égaux:
X: [[[email protected], [email protected]]] y: [[email protected], [email protected]]
Ce résultat est très étrange. Internet n'a pas expliqué pourquoi cette situation s'est produite. Permettez-moi de le proposer ici: la version hibernate que j'utilise est Hibernate 3.3.2.ga. Je ne sais pas si c'est un problème de version ou un autre problème, étudions-le demain. Si quelqu'un sait pourquoi, j'espère que je vais me le dire.