2010-12-03 7 views
21

De acuerdo con la documentación, hibernate 3.6 debe ser compatible con el tipo java.util estadounidenseID. Pero cuando un mapa Información gusta:Problemas al asignar el UUID en JPA/Hibernar

@Id protected UUID uuid; 

consigo la siguiente excepción:

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [test-applicationContext.xml]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: persistenceUnit] Unable to build EntityManagerFactory 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1420) ~[spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE] 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519) ~[spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE] 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456) ~[spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE] 
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291) ~[spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE] 
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE] 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288) ~[spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE] 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190) ~[spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE] 
    at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findDefaultEntityManagerFactory(PersistenceAnnotationBeanPostProcessor.java:529) ~[spring-orm-3.0.5.RELEASE.jar:3.0.5.RELEASE] 
    at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findEntityManagerFactory(PersistenceAnnotationBeanPostProcessor.java:495) ~[spring-orm-3.0.5.RELEASE.jar:3.0.5.RELEASE] 
    at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$PersistenceElement.resolveEntityManager(PersistenceAnnotationBeanPostProcessor.java:656) ~[spring-orm-3.0.5.RELEASE.jar:3.0.5.RELEASE] 
    at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$PersistenceElement.getResourceToInject(PersistenceAnnotationBeanPostProcessor.java:629) ~[spring-orm-3.0.5.RELEASE.jar:3.0.5.RELEASE] 
    at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:147) ~[spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE] 
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:84) ~[spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE] 
    at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.postProcessPropertyValues(PersistenceAnnotationBeanPostProcessor.java:338) ~[spring-orm-3.0.5.RELEASE.jar:3.0.5.RELEASE] 
    ... 51 common frames omitted 
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: persistenceUnit] Unable to build EntityManagerFactory 
    at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:911) ~[hibernate-entitymanager-3.6.0.Final.jar:3.6.0.Final] 
    at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:74) ~[hibernate-entitymanager-3.6.0.Final.jar:3.6.0.Final] 
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:225) ~[spring-orm-3.0.5.RELEASE.jar:3.0.5.RELEASE] 
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:308) ~[spring-orm-3.0.5.RELEASE.jar:3.0.5.RELEASE] 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1477) ~[spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE] 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1417) ~[spring-beans-3.0.5.RELEASE.jar:3.0.5.RELEASE] 
    ... 64 common frames omitted 
Caused by: org.hibernate.MappingException: No Dialect mapping for JDBC type: -2 
    at org.hibernate.dialect.TypeNames.get(TypeNames.java:78) ~[hibernate-core-3.6.0.Final.jar:3.6.0.Final] 
    at org.hibernate.dialect.TypeNames.get(TypeNames.java:103) ~[hibernate-core-3.6.0.Final.jar:3.6.0.Final] 
    at org.hibernate.dialect.Dialect.getTypeName(Dialect.java:249) ~[hibernate-core-3.6.0.Final.jar:3.6.0.Final] 
    at org.hibernate.mapping.Column.getSqlType(Column.java:208) ~[hibernate-core-3.6.0.Final.jar:3.6.0.Final] 
    at org.hibernate.mapping.Table.sqlTemporaryTableCreateString(Table.java:371) ~[hibernate-core-3.6.0.Final.jar:3.6.0.Final] 
    at org.hibernate.mapping.PersistentClass.prepareTemporaryTables(PersistentClass.java:765) ~[hibernate-core-3.6.0.Final.jar:3.6.0.Final] 
    at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:270) ~[hibernate-core-3.6.0.Final.jar:3.6.0.Final] 
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1842) ~[hibernate-core-3.6.0.Final.jar:3.6.0.Final] 
    at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:902) ~[hibernate-entitymanager-3.6.0.Final.jar:3.6.0.Final] 
    ... 69 common frames omitted 

Sé preguntas con trazas de la pila no son muy populares, pero este es un problema muy hibernación específica y han sido incapaz de encontrar nada en google :)

Gracias

+0

Lo RDBMS está usando y qué versión del controlador JDBC está usando? –

+0

MySQL 5.1.47 y mysql-connector 5.1.13 –

+8

En realidad, las preguntas _without_ stacktraces son impopulares. – Bozho

Respuesta

22

UUID era un tipo básico agregado en 3.6. Sin embargo, de forma predeterminada se traduce en un tipo binario JDBC que parece causar problemas para mysql. Puede anular este comportamiento especificando explícitamente uuid-char como el tipo.

+0

Ok, ¿y si quiero contarlo en binario (16)? –

+0

Si ese es el caso, entonces querrás hacer algo parecido a la respuesta de Partenón. Parece como por su comentario a su respuesta que por alguna razón 16 bits no son suficientes. Es probable que la asignación en el controlador jdbc de mysql esté funcionando. Tendré que hacer más investigación para poder proporcionar detalles. Si quieres jugar con él para ver qué sucede, intenta subirlo a binario (32) y ver qué se pone en el db. –

3

no utilice el tipo UUID, porque se necesitaría un tipo personalizado para manejarlo.

Use String. Ver this post. Es una forma de implementarlo.

Otra forma es utilizar el generador UUID incorporado en Hibernate. Necesitaría @GeneratedValue con un generador llamado hibernate-uuid

+3

Usar String no es muy eficiente para consultar y almacenar. Además, ¿se supone que hibernate 3.6 tiene soporte para mapear tipos de UUID? ¿O necesito tenerlo en combinación con @generatedvalue para que funcione? –

+1

¿Y cómo lo almacenará en la base de datos, sino como cadena? – Bozho

+0

Gracias, eso funcionó para mí tratando de conectarme a un servidor MS SQL. – cbmeeks

7
Caused by: org.hibernate.MappingException: No Dialect mapping for JDBC type: -2 

Esto significa que UUID está siendo mapeada como BINARIO [1] por Hibernate, pero ninguno de MySQL Dialectos Mapas BINARIO a un tipo de datos MySQL. Echar un vistazo a la jerarquía dialecto para MySQL:

https://github.com/hibernate/hibernate-core/blob/master/hibernate-core/src/main/java/org/hibernate/dialect/MySQLDialect.java

https://github.com/hibernate/hibernate-core/blob/master/hibernate-core/src/main/java/org/hibernate/dialect/MySQL5Dialect.java

https://github.com/hibernate/hibernate-core/blob/master/hibernate-core/src/main/java/org/hibernate/dialect/MySQL5InnoDBDialect.java

los comparamos con éste (búsqueda de la asignación binario): https://github.com/hibernate/hibernate-core/blob/master/hibernate-core/src/main/java/org/hibernate/dialect/HSQLDialect.java

Este puede ser un error en Hibernate, ya que veo el tipo de datos BINARY a disponible en la documentación de MySQL, pero es posible que desee hacer una búsqueda en JIRA de Hibernate para ver si hay alguna razón por la cual no se haya mapeado.

Si usted está dispuesto a probar, sólo puede MySQL5InnoDBDialect subclase (si está utilizando InnoDB), y usar esto para el constructor:

registerColumnType(Types.BINARY, "binary"); 

Por lo tanto, esta es la razón por la cadena está trabajando, pero java.utilidenseID no lo es.

1-http://download.oracle.com/javase/6/docs/api/constant-values.html#java.sql.Types.BINARY

+0

Lo hice y obtuve esto en su lugar: com.mysql.jdbc.MysqlDataTruncation: Truncamiento de datos: datos demasiado largos para la columna 'uuid' en la fila 1 –

+0

Leía la documentación de MySQL sobre esto, y trataba de encontrar una forma de almacenar estos datos binarios UUID en una columna MySQL con el tipo de datos como binario usando solo JDBC. Si puede hacer eso usando JDBC puro, entonces Hibernate también debería ser capaz de hacerlo. En este caso, abra un problema en Hibernate JIRA con tantos detalles como sea posible (puntos de bonificación si adjunta casos de prueba). Estoy bastante seguro de que la buena gente de Hibernate lo aceptará y estará encantado de recibir tu contribución. – jpkrohling

26

La extensión de la respuesta de Mike animado con un ejemplo de código & refiriéndose a Oracle también.

Tuve este problema con OracleDialect (Oracle10gDialect). Al agregar una anotación @Type al campo UUID, se corrigió por mí.

@Id 
@Type(type="uuid-char") 
private UUID id; 

Nota: también se utiliza un TwoWayStringBridge en este campo, utilizando la anotación @FieldBridge.

Nota: type = "uuid-binary" no funcionó; tiene el mismo error de tipo desconocido.

+1

¿Existe alguna propiedad global para establecer esto como asignación predeterminada para todo java.utilídID a uuid-char para que no tenga que escribir esta anotación para cada entidad que use UUID? (También quiero evitar la anotación específica de hibernación en mi código y dejarlo todo javax.persistance. –

+1

¡Sí! Consulte la respuesta de jpkrohling a continuación. Solo personalice el dialecto de su base de datos y registre el tipo de columna en su constructor. – Barett

7

Utilizando Hibernate 4 y MySQL 5.5 con una tabla InnoDB, pude almacenar una columna UUID como BINARY(16) tal como está (no se requiere configuración o tipo personalizado). No estoy usando esto como ID de entidad y estoy creando el valor manualmente usando UUID.randomUUID().

@Entity 
@Table(name = "post") 
public class PostModel implements Serializable 
{ 
    ... 
    @Column(name = "uuid", nullable = false, updatable = false) 
    private UUID uuid; 
    ... 
} 

> desc post; 
+----------------+---------------+------+-----+---------------------+ 
| Field   | Type   | Null | Key | Default    | 
+----------------+---------------+------+-----+---------------------+ 
| ...   |    |  |  |      | 
| uuid   | binary(16) | YES | UNI | NULL    | 
| ...   |    |  |  |      | 
+----------------+---------------+------+-----+---------------------+ 
+1

¿Cómo recupera los valores? UUID? – daydreamer

+0

Hibernate hace la asignación automáticamente. ¿Su código coincide con lo que agregué a mi respuesta? –

+0

¡Esta es la mejor respuesta para Hibernate 4 y superior! – HopeKing

0

Google búsqueda me llevó a este post cuando yo estaba buscando para el mapeo UUID con JDBC por lo que voy a publicar mi experiencia, si no le importa.

En mi proyecto estoy cambiando entre H2 y MySql usando H2 en pruebas unitarias. H2 es compatible nativamente con el tipo de UUID. Pero el conector java mysql no. Así que mi única opción es convertir BINARY(16) a UUID en código de cliente que no me gusta.

Como resultado he corregido el conector mysql java oficial para tratar el UUID como BINARIO (16). Sé que es un poco hacky pero funciona para mí.

Si quieres probar que lo publicado en github: http://goo.gl/NIhNi

Cuestiones relacionadas