33

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

@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$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

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

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
Piotr
  • 4,813
  • 7
  • 35
  • 46

6 Answers6

51

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

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

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

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

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

Barett
  • 5,826
  • 6
  • 51
  • 55
  • 1
    Is there any global property to set this as default mapping for all java.util.UUID to uuid-char so I don't have to type this annotation for every entity using UUID? (I also want to avoid hibernate specific annotation in my code and leave it all javax.persistance. – L. Holanda Dec 21 '16 at 22:58
  • 1
    Yes! See jpkrohling's answer below. Just customize your database dialect and register the column type in its constructor. – Barett Dec 24 '16 at 01:51
  • 1
    Inspired by this answer, I got spring JPA working with Oracle DB (In Kotlin): ```@Column(name = "uuid") @Type(type="uuid-char") var uuid: UUID? = null.``` When using it, ```val x = UUID.fromString("00a023b3-1357-3070-a661-72a09f8ccdb2")``` to convert from str to uuid. On Oracle db: ```ALTER TABLE ADD UUID RAW(16) default SYS_GUID() NOT NULL```. – Emily Jun 13 '19 at 17:56
  • Thanks @Emily!! Glad this helped inspire you. – Barett Nov 23 '19 at 01:02
  • 2
    This was a life saver. Thank you – Shweta Valunj Apr 28 '21 at 14:00
38

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.

Mike Lively
  • 1,008
  • 1
  • 8
  • 9
  • Ok, what if I want to story it in binary(16)? – Piotr Dec 03 '10 at 16:21
  • If that is the case then you will want to do something akin to partenon's answer. It sounds as though from your comment to his answer that for whatever reason 16 bits are not enough. It is probably how the mapping in mysql's jdbc driver is working. I'll need to do more research to be able to provide specifics. If you want to play around with it to see what's happening try upping it to binary(32) and seeing what gets put in the db. – Mike Lively Dec 03 '10 at 17:28
10

Using Hibernate 4 and MySQL 5.5 with an InnoDB table, I was able to store a UUID column 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().

@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                |
| ...            |               |      |     |                     |
+----------------+---------------+------+-----+---------------------+
David Harkness
  • 35,992
  • 10
  • 112
  • 134
9
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:

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

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

This may be 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.

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

registerColumnType( Types.BINARY, "binary" );

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

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

jpkroehling
  • 13,881
  • 1
  • 37
  • 39
  • I did that and got this instead: com.mysql.jdbc.MysqlDataTruncation: Data truncation: Data too long for column 'uuid' at row 1 – Piotr Dec 03 '10 at 16:42
  • I would read the MySQL documentation about this, and I would try to come up with a way to store this UUID binary data into a MySQL column with data type as binary using JDBC only. If you are able to do that using pure JDBC, then Hibernate should also be able to. In this case, open a issue in Hibernate JIRA with as much details as possible (bonus points if you attach test cases). I'm quite sure the fine folks at Hibernate will accept it and will be glad to get your contribution. – jpkroehling Dec 04 '10 at 09:48
3

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

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

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

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
  • 9
    Using String is not very efficient for querying and storage. Also, hibernate 3.6 is supposed to have support for mapping of UUID types? Or do I need to have it in combination with @generatedvalue for it to work? – Piotr Dec 03 '10 at 15:51
  • 1
    And how will you store it in the database, if not as string? – Bozho Dec 03 '10 at 15:53
  • Thanks, that worked for me trying to connect to a MS SQL server. – cbmeeks Feb 04 '11 at 18:54
  • 1
    Using UUID and not String has one key advantage, you will never need to worry about upper or lower case id's. In my app ids were coming from different sources so the case could differ sometimes which caused some trouble when comparing them. – Broccoli Jan 23 '17 at 15:12
  • I'm using String, and the issue here https://stackoverflow.com/questions/41651681 happens to me, so it is not a solution. – Al-Mothafar May 15 '19 at 05:20
  • Link in answer is outdated. – Pang Aug 04 '23 at 03:27
1

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.

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 UUID in client code which I don't like.

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

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

expert
  • 29,290
  • 30
  • 110
  • 214