Eu vi recentemente o tipo personalizado de hibernato. Eu nunca fui exposto a isso antes. Vou gravá -lo aqui como uma consolidação do meu conhecimento e deixarei amigos que nunca foram expostos a aprender e estudá -lo juntos.
1) Os tipos personalizados, como o nome sugerem, são obviamente tipos que são implementados por si mesmos porque os tipos internos não atendem às necessidades. Não há muitas situações, mas ainda precisamos aprender. Se tivermos mais habilidades, não suprimiremos nosso corpo. Aprenda também como os outros consideram como pensar sobre extensibilidade ao fazer estruturas.
Existem duas maneiras de implementar tipos personalizados, um é implementar o UserType, o outro é implementar o ComposetSuserType, e pode haver alguns métodos, mas eu não o usei por enquanto, então não vou falar sobre isso por enquanto.
Estou apenas usando o userType por enquanto, vamos primeiro olhar para a definição da interface do userType:
Public Interface UserType { /*** Retorne os códigos do tipo SQL para as colunas mapeadas por esse tipo. Os códigos * são definidos em <tt> java.sql.types </tt>. */ public int [] sqltypes (); /*** A classe retornada por <tt> nullsafeget () </tt>. */ classe pública returnclass (); /*** Compare duas instâncias da classe mapeada por esse tipo de persistência "igualdade". * Igualdade do estado persistente. */ Public boolean é igual (objeto x, objeto y) lança hibernateException; / ** * Obtenha um código de hash para a instância, consistente com a persistência "igualdade" */ public int hashCode (objeto x) lança hibernateException; /*** Recupere uma instância da classe mapeada de um conjunto de resultados JDBC. Os implementadores * devem lidar com a possibilidade de valores nulos. */ Public Object NullSafeget (ResultSet RS, String [] Nomes, Proprietário do Objeto) lança HibernateException, SQLEXCIPCECCETION; /*** Escreva uma instância da classe mapeada para uma declaração preparada. Os implementadores * devem lidar com a possibilidade de valores nulos. Um tipo de várias colunas deve ser escrito * para parâmetros a partir de <tt> Índice </tt>. */ public void nullSafeset (preparado estatement s st, valor de objeto, índice int) lança hibernateException, sqLexception; /** * Retorne uma cópia profunda do estado persistente, parando em entidades e em * coleções. Não é necessário copiar objetos imutáveis ou valores nulos *, caso em que é seguro simplesmente retornar o argumento. */ Public Object DeepCopy (valor do objeto) lança HibernateException; /*** Os objetos desse tipo são mutáveis? * * @return boolean */ public boolean ismutable (); /*** Transforme o objeto em sua representação em cache. No mínimo, esse método * deve executar uma cópia profunda se o tipo for mutável. Isso pode não ser suficiente * para algumas implementações, no entanto; Por exemplo, as associações devem ser armazenadas em cache como * valores de identificador. (operação opcional) * * @param valor o objeto a ser armazenado em cache * @return Uma representação em cache do objeto * @throws hibernateException */ desmontagem serializável pública (valor do objeto) lança hibernateException; /*** Reconstrua um objeto da representação em cache. No mínimo, esse método * deve executar uma cópia profunda se o tipo for mutável. (Operação opcional) */ Public Object Assemble (cache serializável, proprietário do objeto) lança HibernateException; /** * Durante a mesclagem, substitua o valor (destino) existente na entidade que somos mesclados * com um novo valor (original) da entidade isolada que estamos mesclando. Para objetos imutáveis *, ou valores nulos, é seguro simplesmente retornar o primeiro parâmetro. Para * objetos mutáveis, é seguro retornar uma cópia do primeiro parâmetro. Para objetos * com valores de componentes, pode fazer sentido substituir recursivamente os valores dos componentes. */ Public Object Replicar (objeto original, destino do objeto, proprietário do objeto) lança HibernateException; } Na verdade, você pode entendê -lo em inglês em geral, para que não explique mais. Aqui, a principal coisa que devemos implementar o método NullSafeset (). Este método usa principalmente a economia desse tipo de valor no banco de dados. Desta vez, aprenderemos como usá -lo primeiro e depois estudaremos lentamente como ele é implementado internamente.
2) Os exemplos que escrevi quando estudava estavam se referindo ao exemplo de Xia Xin, por isso é definitivamente o mesmo que a maioria dos online. Vamos analisá -lo aproximadamente:
Abaixo está a classe de usuário
pacote org.hibernate.tutorial.Domain; importar java.io.serializable; importar java.util.list; classe pública o usuário implementa serializável {public Long Id; nome de string privado; e -mails de lista privada; Omita o método Get/Set} Em seguida é a classe Emaillist personalizada:
pacote org.hibernate.tutorial.Domain; importar java.io.serializable; importar java.SQL.PreparedStatement; importar java.sql.resultset; importar java.sql.sqLexception; importar java.sql.sql.types; importar java.util.arraylist; importar java.util.list; importar org.hibernate.hibernate; importar org.hibernate.hibernateException; importar org.hibernate.UserType.UserType; classe pública Emaillist implementa o userType {private static final char splitter = ';'; private estático final int [] tipos = new int [] {types.varchar}; String Private String (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 (); } lista privada parse (valor da string) {string [] strs = org.hibernate.util.stringhelper.split (value, string.valueof (splitter)); Listar emaillist = new ArrayList (); for (int i = 0; i <strs.lengn; i ++) {emaillist.add (strs [i]); } retornar emaillist; } public Object DeepCopy (Valor do objeto) lança HibernateException {List Sourcelist = (List) Value; List TargetList = new ArrayList (); TargetList.add (Sourcelist); retornar TargetList; } desmontagem serializável pública (valor do objeto) lança hibernateException {return null; } public boolean é igual (objeto x, objeto y) lança hibernateException {if (x == y) retorna true; System.out.println ("x:"+x+"y:"+y); if (x! = null && y! = null) {list xlist = (list) x; Lista ylist = (list) y; if (xlist.size ()! = ylist.size ()) retorna 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)) retornar false; } retornar true; } retornar false; } public boolean ismutable () {return false; } public Object nullSafeget (ResultSet RS, String [] Nomes, Proprietário do objeto) lança HibernateException, SQLEXCECCIONY {String Value = (String) Hibernate.String.NullSafeget (rs, nomes [0]); if (value! = null) {return parse (valor); // lista de pasta; dividido} else {return null; }} public void nullSafeset (preparado estatement s st, valor de objeto, int index) lança hibernateException, sqlexception {System.out.println ("set método executado!"); System.out.println ("valor:" + valor); if (value! = null) {string str = montagem ((list) valor); // use strings; Splice hibernate.string.nullSafeset (st, str, índice); } else {hibernate.string.nullSafeset (st, value, index); }} public class ReturnedClass () {return list.class; } public int [] sqltypes () {retorna tipos; } // omita outros métodos que não requerem modificação} Os métodos implementados na classe são métodos que precisam ser modificados e outros métodos que não precisam ser modificados por enquanto não foram escritos, mas ainda precisam ser implementados.
3) Em seguida, é o arquivo de mapeamento da classe de usuário:
<classe name = "user" tabela = "user"> <id name = "id" column = "user_id" type = "java.lang.long"> <generator/> </dod> <names name = "name" type = "string" column = "user_name"/> <names = "emails" = "ou" ou "ou" ou "ou emails".
Eu acredito que todo mundo sabe como modificá -lo, e não vou explicar aqui. Ele altera principalmente o tipo de emails e o altera para a classe emaillista que acabamos de definir.
4) Finalmente, vamos escrever uma aula de teste:
importar java.util.hashmap; importar java.util.list; importar java.util.map; importar 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; classe pública HibernatEtest estende o teste {Sessão privada de sessão = null; Protected void setup () lança Exceção {Configuration cfg = new Configuration (). Configure (); Sessionfactory sessfactory = cfg.buildSessionFactory (); session = sessionFactory.opensssion (); } public void testInsert () {transação TRAN = null; tente {Tran = session.BegIntransaction (); Usuário do usuário = novo usuário (); user.setName ("Shun"); Lista da lista = new ArrayList (); list.add ("[email protected]"); list.add ("[email protected]"); user.setEmails (lista); session.Save (usuário); Tran.Commit (); } catch (Exceção ex) {ex.PrintStackTrace (); if (Tran! = null) {Tran.rollback (); }} void protegido telção downswn () lança a exceção {session.close (); }} Pode haver um problema aqui. Quando salvarmos apenas um email, ele terá uma exceção. O campo de email no banco de dados está vazio. Quando tivermos dois códigos como o código acima, não haverá problema. O resultado no banco de dados é como mostrado na figura:
E quando salvamos apenas um, a exceção é a seguinte:
java.lang.classCastException: java.util.arraylist não pode ser lançado para java.lang.string
Ocorre no método igual do emaillista, string str1 = (string) xlist.get (i); Nesse código, após a verificação, ele se torna uma lista de lista ao inserir dados e passá -los para o método NullSafeset do Emaillist, ou seja,
Valor: [[[email protected], [email protected]]] Este formulário causará problemas ao comparar. Sempre tem apenas um valor, mas é diferente ao comparar.
if (xlist.size ()! = ylist.size ()) retorna false;
Portanto, haverá problemas ao lançar.
Após a inspeção, o método igual:
X: [[[email protected], [email protected]] y: [[email protected], [email protected]]
Este resultado é muito estranho. A Internet não falou sobre por que essa situação ocorreu. Deixe -me propor aqui: a versão Hibernate que eu uso é Hibernate 3.3.2.ga. Não sei se é um problema de versão ou outro problema, vamos estudá -lo amanhã. Se alguém souber o porquê, espero me dizer.