Recientemente vi el tipo personalizado de hibernado. Nunca antes había estado expuesto a eso. Lo grabaré aquí como una consolidación de mi conocimiento y dejaré que los amigos que nunca hayan estado expuestos a aprender y estudiarlo juntos.
1) Los tipos personalizados, como su nombre indica, son, por supuesto, los tipos que son implementados por ellos mismos porque los tipos internos no satisfacen las necesidades. No hay muchas situaciones de este tipo, pero aún necesitamos aprenderlo. Si tenemos más habilidades, no suprimiremos nuestro cuerpo. También aprenda cómo otros consideran cómo pensar en la extensibilidad al hacer marcos.
Hay dos formas de implementar tipos personalizados, uno es implementar UserType, el otro es implementar CompositeUsertype, y puede haber algunos métodos, pero no lo he usado por el momento, por lo que no hablaré de ello por ahora.
Solo estoy usando Usertype por el momento, veamos primero la definición de la interfaz Usertype:
interfaz pública usertype { /*** Devuelve los códigos de tipo SQL para las columnas asignadas por este tipo. Los códigos * se definen en <tt> java.sql.types </tt>. */ public int [] sqltypes (); /*** La clase devuelta por <TT> nullSafeget () </tt>. */ clase pública returnedClass (); /*** Compare dos instancias de la clase mapeada por este tipo para la persistencia "igualdad". * Igualdad del estado persistente. */ público booleano iguales (objeto x, objeto y) arroja hibernateException; / ** * Obtenga un hashcode para la instancia, de acuerdo con la persistencia "igualdad" */ public int hashcode (objeto x) arroja hibernateException; /*** Recupere una instancia de la clase mapeada de un conjunto de resultados JDBC. Los implementadores * deben manejar la posibilidad de valores nulos. */ Public Object NullSafeget (ResultSet RS, String [] nombres, propietario del objeto) lanza HibernateException, SQLException; /*** Escriba una instancia de la clase mapeada a una declaración preparada. Los implementadores * deben manejar la posibilidad de valores nulos. Se debe escribir un tipo de múltiples columnas * a parámetros que comienzan desde <TT> índice </tt>. */ public void nullSafeset (preparado ST, valor de objeto, índice int) lanza HibernateException, SQLException; /** * Devuelve una copia profunda del estado persistente, deteniéndose en entidades y en * colecciones. No es necesario copiar objetos inmutables, o valores nulos *, en cuyo caso es seguro simplemente devolver el argumento. */ Public Object DeepCopy (valor de objeto) arroja hibernateException; /*** ¿Son los objetos de este tipo mutables? * * @return boolean */ public boolean isMutable (); /*** Transforme el objeto en su representación en caché. Por lo menos, este método * debe realizar una copia profunda si el tipo es mutable. Sin embargo, eso puede no ser suficiente * para algunas implementaciones; Por ejemplo, las asociaciones deben almacenarse en caché como * valores de identificador. (Operación opcional) * * @param Valor El objeto se almacenará en caché * @return una representación en caché del objeto * @throws hibernateException */ public Serializable Dissemble (valor de objeto) arroja hibernateException; /*** Reconstruya un objeto a partir de la representación almacenable. Por lo menos, este método * debe realizar una copia profunda si el tipo es mutable. (Operación opcional) */ Public Object Ensamble (Serializable en caché, propietario del objeto) lanza HibernateException; /** * Durante la fusión, reemplace el valor (objetivo) existente en la entidad que nos fusionamos * con un nuevo valor (original) de la entidad separada que estamos fusionando. Para objetos inmutables *, o valores nulos, es seguro simplemente devolver el primer parámetro. Para * objetos mutables, es seguro devolver una copia del primer parámetro. Para los objetos * con valores de componentes, podría tener sentido reemplazar recursivamente los valores de los componentes. */ Public Object Reemplazar (Objeto original, objetivo de objeto, propietario del objeto) lanza HibernateException; } De hecho, puedes entenderlo en inglés en general, por lo que no lo explicaré más. Aquí, lo principal que somos para implementar el método NullSafeset (). Este método utiliza principalmente guardar este tipo de valor en la base de datos. Esta vez aprenderemos cómo usarlo primero, y luego estudiaremos lentamente cómo se implementa internamente.
2) Los ejemplos que escribí cuando estudiaba se referían al ejemplo de Xia Xin, por lo que definitivamente es lo mismo que la mayoría de los en línea. Vamos a analizarlo más o menos:
A continuación se muestra la clase de usuario
paquete org.hibernate.tutorial.domain; import java.io.serializable; import java.util.list; El usuario de la clase pública implementa serializable {public Long Id; nombre de cadena privada; correos electrónicos de la lista privada; omitir el método get/set} El siguiente es la clase de emailista personalizada:
paquete org.hibernate.tutorial.domain; import java.io.serializable; import java.sql.preparedStatement; import java.sql.resultset; import java.sql.sqlexception; import java.sql.sql.types; import java.util.arrayList; import java.util.list; importar org.hibernate.Hibernate; importar org.hibernate.HibernateException; importar org.hibernate.usertype.usertype; La clase pública Emaillist implementa Usertype {private estático final char splitter = ';'; Private static final int [] tipos = new int [] {tipos.varchar}; string private string ensamble (list emaillist) {StringBuilder strBuf = new StringBuilder (); para (int i = 0; i <eMaillist.size () - 1; i ++) {strbuf.append (emaillist.get (i)). append (divisor); } strbuf.append (Emaillist.get (Emaillist.Size ()-1)); return strBuf.ToString (); } PRIVADA LIST PARSE (VALOR DE STRING) {String [] strs = org.hibernate.util.stringhelper.split (valor, string.valueOf (divisor)); Lista EMAILLIST = new ArrayList (); para (int i = 0; i <strs.length; i ++) {emaillist.add (strs [i]); } return Emaillist; } Public Object DeepCopy (valor de objeto) lanza HibernateException {List SourCelist = (List) Value; List TargetList = new ArrayList (); TargetList.Add (Sourcelist); return TargetList; } public Serializable Dissensemble (valor del objeto) lanza HibernateException {return null; } public boolean iguales (objeto x, objeto y) arroja 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; for (int i = 0; i <xlist.size (); i ++) {string str1 = (string) xlist.get (i); Cadena str2 = (string) ylist.get (i); if (! str1.equals (str2)) return false; } return verdadero; } return false; } public boolean isMutable () {return false; } Public Object nullSafeget (ResultSet RS, String [] nombres, propietario del objeto) lanza HibernateException, SqLException {String value = (String) Hibernate.String.NullSafeget (RS, nombres [0]); if (value! = null) {return parse (valor); // pegar lista; Split} else {return null; }} public void nullSafeSet (preparado Statement st, valor de objeto, int index) arroja hibernateException, sqlexception {system.out.println ("¡Establecer método ejecutado!"); System.out.println ("Valor:" + valor); if (value! = null) {string str = ensamble ((list) value); // use cadenas; empalme hibernate.string.nullSafeset (st, str, índice); } else {hibernate.string.nullSafeset (st, valor, índice); }} public class returnedClass () {return list.class; } public int [] sqltypeS () {tipos de retorno; } // omitir otros métodos que no requieren modificación} Los métodos implementados en la clase son métodos que deben modificarse, y otros métodos que no necesitan ser modificados por el momento no se han escrito, pero aún deben implementarse.
3) El siguiente es el archivo de asignación de la clase de usuario:
<class name = "user" table = "user"> <id name = "id" columna = "user_id" type = "java.lang.long"> <generador/> </id> <propiedad name = "name" type = "string" column = "user_name"/> <propiedad name = "correos electrónicos" type = "org.hibernate.tutorial.domain.emaillist.
Creo que todos saben cómo modificarlo, y no lo explicaré aquí. Cambia principalmente el tipo de correos electrónicos y lo cambia a la clase Emaillist que acabamos de definir.
4) Finalmente, escribamos una clase de prueba:
import java.util.hashmap; import java.util.list; import java.util.map; import java.util.arrayList; import junit.framework.testcase; importar org.hibernate.entityMode; importar org.hibernate.session; importar org.hibernate.sessionFactory; importar org.hibernate.transaction; importar org.hibernate.cfg.configuration; importar org.hibernate.tutorial.domain.user; clase pública HibernateTest extiende TestCase {Session private Session = NULL; Protected void setup () lanza la excepción {Configuración cfg = nueva configuración (). Configuración (); SessionFactory sessionFactory = cfg.BuildSessionFactory (); session = sessionFactory.opensession (); } public void testInsert () {Transaction tran = null; intente {tran = session.beGinTransaction (); Usuario user = nuevo usuario (); user.setName ("shun"); List List = new ArrayList (); list.add ("[email protected]"); list.add ("[email protected]"); user.setEmails (lista); session.save (usuario); tran.commit (); } catch (Exception Ex) {Ex.PrintStackTrace (); if (tran! = null) {tran.rollback (); }} protegido void sattardown () lanza la excepción {session.close (); }} Puede haber un problema aquí. Cuando solo guardemos un correo electrónico, tendrá una excepción. El campo de correo electrónico en la base de datos está vacío. Cuando tenemos dos códigos como el código anterior, no habrá problema. El resultado en la base de datos es como se muestra en la figura:
Y cuando guardamos solo uno, la excepción es la siguiente:
java.lang.classcastException: java.util.arraylist no puede ser elegido a java.lang.string
Ocurre en el método igual de Emaillist, String str1 = (String) xList.get (i); En este código, después de verificar, se convierte en una lista de la lista al insertar datos y pasarlo al método NULLSAFESET de Emaillist, es decir, es.
Valor: [[[email protected], [email protected]]]] Este formulario causará problemas al comparar. Siempre tiene solo un valor, pero es diferente al comparar.
if (xlist.size ()! = ylist.size ()) return false;
Entonces habrá problemas al lanzar.
Después de la inspección, el método igual:
X: [[[email protected], [email protected]]] Y: [[email protected], [email protected]]
Este resultado es muy extraño. Internet no habló sobre por qué ocurrió esta situación. Permítanme proponerlo aquí: la versión hibernada que uso es Hibernate 3.3.2.Ga. No sé si es un problema de versión u otro problema, estudiemos mañana. Si alguien sabe por qué, espero decirme.