在JPA / hibernate中映射UUID的问题

时间:2010-12-03 15:16:20

标签: java hibernate jpa uuid

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

@Id protected UUID uuid;

我得到以下异常:

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

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

由于

6 个答案:

答案 0 :(得分:35)

使用代码示例扩展Mike Lively的答案&amp;也指甲骨文。

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

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

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

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

答案 1 :(得分:27)

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

答案 2 :(得分:9)

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

答案 3 :(得分:7)

将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                |
| ...            |               |      |     |                     |
+----------------+---------------+------+-----+---------------------+

答案 4 :(得分:3)

请勿使用UUID类型,因为您需要自定义类型来处理它。

使用String。见this post。这是实现它的一种方式。

另一种方法是使用hibernate内置的UUID生成器。您需要使用名为@GeneratedValue

的生成器hibernate-uuid

答案 5 :(得分:0)

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

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

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

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