在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层次结构:
比较它们(搜索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