Ответ 1
UUID был базовым типом, добавленным в 3.6. Однако по умолчанию он преобразуется в двоичный тип JDBC, который, как представляется, вызывает проблемы для mysql. Вы можете переопределить это поведение, явно указав uuid- char как тип.
Согласно документации, 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
Я знаю, что вопросы со стековыми трассами не очень популярны, но это очень проблема с гибернацией, и я не смог ничего найти в google:)
Спасибо
UUID был базовым типом, добавленным в 3.6. Однако по умолчанию он преобразуется в двоичный тип JDBC, который, как представляется, вызывает проблемы для mysql. Вы можете переопределить это поведение, явно указав uuid- char как тип.
Расширение Mike Lively ответит образцом кода и ссылается на Oracle тоже.
У меня была эта проблема с OracleDialect (Oracle10gDialect). Добавление аннотации @Type в поле UUID исправило это для меня.
@Id
@Type(type="uuid-char")
private UUID id;
Примечание: также используется TwoWayStringBridge в этом поле, используя аннотацию @FieldBridge.
Примечание: type = "uuid-binary" не работает; получил ту же ошибку неизвестного типа.
Caused by: org.hibernate.MappingException: No Dialect mapping for JDBC type: -2
Это означает, что UUID сопоставляется BINARY [1] по Hibernate, но ни один из них не отображает BINARY для типа данных MySQL. Взгляните на иерархию Dialect для MySQL:
Сравните их с этим (поиск отображения BINARY): https://github.com/hibernate/hibernate-core/blob/master/hibernate-core/src/main/java/org/hibernate/dialect/HSQLDialect.java
Это может быть ошибка в Hibernate, так как я вижу тип данных BINARY, доступный в документации по MySQL, но вы можете сделать некоторый поиск в 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)
как есть (не требуется конфигурация или настраиваемый тип). Я не использую это как идентификатор объекта и создаю значение вручную с помощью 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
. См. этот пост. Это один из способов его реализации.
Другой способ - использовать генератор UUID, встроенный в спящий режим. Вам понадобится @GeneratedValue
с генератором с именем hibernate-uuid
Поиск Google привел меня к этому сообщению, когда я искал сопоставление UUID с JDBC, поэтому я отправлю свой опыт, если вы не возражаете.
В моем проекте я переключаюсь между H2 и MySql, используя H2 в модульном тестировании. H2 поддерживает тип UUID. Но mysql java коннектор не делает. Поэтому мой единственный вариант - преобразовать BINARY(16)
в UUID
в код клиента, который мне не нравится.
В результате я исправил официальный mysql java-коннектор для обработки UUID как BINARY (16). Я знаю, что это хаки, но работает для меня.
Если вы хотите попробовать, я разместил его на github: http://goo.gl/NIhNi