Java 在 JPA/hibernate 中映射 UUID 的问题

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4346898/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 16:17:33  来源:igfitidea点击:

Problems mapping UUID in JPA/hibernate

javahibernatejpauuid

提问by Piotr

According to the documentation, hibernate 3.6 should have support for the java.util.UUID type. But when I map it like:

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

@Id protected UUID uuid;

I get the following 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.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

I know questions with stack traces are not very popular but this is a very hibernate-specific problem and I have been unable to find anything on google :)

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

Thanks

谢谢

采纳答案by Mike Lively

UUID was a basic type added in 3.6. However, by default it translates to a JDBC Binary type which appears to cause issues for mysql. You can override this behavior by explicitly specifying uuid-char as the type.

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

回答by Bozho

Don't use the type UUID, because you'd need a custom type to handle it.

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

Use String. See this post. It is one way of implementing it.

使用String. 看到这个帖子。这是实现它的一种方式。

Another way is to use the UUID generator built in hibernate. You'd need @GeneratedValuewith a generator named hibernate-uuid

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

回答by jpkrohling

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

This means that UUID is being mapped as BINARY[1] by Hibernate, but none MySQL Dialects maps BINARY to a MySQL data type. Take a look at the Dialect hierarchy for MySQL:

这意味着 UUID 被 Hibernate 映射为 BINARY[1],但没有任何 MySQL 方言将 BINARY 映射到 MySQL 数据类型。看一下 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/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/MySQL5Dialect.java

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

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

Compare them with this one (search for the BINARY mapping): https://github.com/hibernate/hibernate-core/blob/master/hibernate-core/src/main/java/org/hibernate/dialect/HSQLDialect.java

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

This maybe a bug in Hibernate, as I do see the BINARY data type available in the MySQL documentation, but you may want to do some search in Hibernate's JIRA to see if there's any reason why this is not mapped.

可能是 Hibernate 中的一个错误,因为我确实在 MySQL 文档中看到了 BINARY 数据类型,但是您可能希望在 Hibernate 的 JIRA 中进行一些搜索,以查看是否有任何原因未映射。

If you are willing to test, you can just subclass MySQL5InnoDBDialect (if you are using InnoDB), and use this to the constructor:

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

registerColumnType( Types.BINARY, "binary" );

So, this is the reason why the String is working, but java.util.UUID is not.

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

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

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

回答by Barett

Extending Mike Lively's answer with a code sample & referring to Oracle too.

使用代码示例扩展 Mike Lively 的回答并参考 Oracle。

I had this problem with the OracleDialect (Oracle10gDialect). Adding an annotation @Type to the UUID field fixed it for me.

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

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

Note: also used a TwoWayStringBridge on this field, using the @FieldBridge annotation.

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

Note: type="uuid-binary" did not work; got the same, unknown type error.

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

回答by David Harkness

Using Hibernate 4 and MySQL 5.5 with an InnoDB table, I was able to store a UUIDcolumn as BINARY(16)as-is (no configuration or custom type required). I am not using this as the entity ID and am creating the value manually using UUID.randomUUID().

使用带有 InnoDB 表的 Hibernate 4 和 MySQL 5.5,我能够UUIDBINARY(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                |
| ...            |               |      |     |                     |
+----------------+---------------+------+-----+---------------------+

回答by expert

Google search led me to this post when I was looking for UUID mapping with JDBC so I'll post my experience if you don't mind.

当我寻找使用 JDBC 的 UUID 映射时,Google 搜索将我带到了这篇文章,因此如果您不介意,我会发布我的经验。

On my project I'm switching between H2 and MySql using H2 in unit-testing. H2 natively supports UUID type. But mysql java connector doesn't. So my only option is to convert BINARY(16)to UUIDin client code which I don't like.

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

As result I patched official mysql java connector to treat UUID as BINARY(16). I know it's kinda hacky but works for me.

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

If you want to try it I posted it on github: http://goo.gl/NIhNi

如果你想试试,我把它贴在 github 上:http: //goo.gl/NIhNi