在JPA / hibernate中映射UUID的问题

根据文档,hibernate 3.6应该支持java.util.UUID类型。 但是当我将其映射为:

@Id protected UUID uuid; 

我得到以下exception:

 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.(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 

我知道堆栈跟踪的问题不是很受欢迎,但这是一个非常特殊的hibernate问题,我一直无法在谷歌上找到任何东西:)

谢谢

UUID是3.6中添加的基本类型。 但是,默认情况下,它会转换为JDBC二进制类型,这似乎会导致mysql出现问题。 您可以通过显式指定uuid-char作为类型来覆盖此行为。

使用代码示例扩展Mike Lively的答案并引用Oracle。

我在OracleDialect(Oracle10gDialect)中遇到了这个问题。 在UUID字段中添加注释@Type为我修复了它。

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

注意:还使用@FieldBridge注释在此字段上使用了TwoWayStringBridge。

注意:type =“uuid-binary”不起作用; 得到了相同的未知类型错误。

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

这意味着Hibernate将UUID映射为BINARY [1],但没有MySQL Dialects将BINARY映射到MySQL数据类型。 看一下MySQL的Dialect层次结构:

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

比较它们(搜索BINARY映射): https : //github.com/hibernate/hibernate-core/blob/master/hibernate-core/src/main/java/org/hibernate/dialect/HSQLDialect.java

可能是Hibernate中的一个错误,因为我确实看到了MySQL文档中提供的BINARY数据类型,但你可能想在Hibernate的JIRA中进行一些搜索,看看是否有任何理由没有映射。

如果您愿意测试,可以将MySQL5InnoDBDialect子类化(如果您使用的是InnoDB),并将其用于构造函数:

 registerColumnType( Types.BINARY, "binary" ); 

所以,这就是String工作的原因,但java.util.UUID不是。

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

使用Hibernate 4和MySQL 5.5和InnoDB表,我能够将UUID列按原样存储为BINARY(16) (不需要配置或自定义类型)。 我没有使用它作为实体ID,并使用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 | | ... | | | | | +----------------+---------------+------+-----+---------------------+ 

不要使用UUID类型,因为您需要一个自定义类型来处理它。

使用String 。 看这篇文章 。 这是实现它的一种方式。

另一种方法是使用hibernate内置的UUID生成器。 你需要@GeneratedValue和一个名为hibernate-uuid的生成器

当我在寻找使用JDBC的UUID映射时,谷歌搜索引导我发布这篇文章,所以如果你不介意我会发布我的经验。

在我的项目中,我在unit testing中使用H2在H2和MySql之间切换。 H2原生支持UUID类型。 但mysql java连接器没有。 所以我唯一的选择是在我不喜欢的客户端代码中将BINARY(16)转换为UUID

结果我修补了官方的mysql java连接器,将UUID视为BINARY(16)。 我知道这有点hacky但对我有用。

如果您想尝试一下,我将其发布在github上: http : //goo.gl/NIhNi