loesak
loesak

Reputation: 1613

Hibernate 5 breaks legacy handling of Java UUID in Postgresql

Upgrading one of our framework libraries caused our version of Hibernate to upgrade from 4 to 5. In doing so, now our queries to our PostgreSQL database are failing with the following exception.

Caused by: org.postgresql.util.PSQLException: ERROR: operator does not exist: bytea = uuid Hint: No operator matches the given name and argument type(s). You might need to add explicit type casts.
Position: 1827

The problem seems to be converting from bytea to a Java UUID. All of our record id's are Java UUID's written to bytea to the database as was the norm in Hibernate 4. Below is the JPA annotations used to define the id field. We had no issues with this in Hibernate 4 and I suspect that I need to changes my annotations to get it to work again in Hibernate 5

@Id
@GeneratedValue(generator = "uuid2")
@GenericGenerator(name = "uuid2", strategy = "uuid2")
private UUID id;

I noticed that a change added to org.hibernate.type.PostgresUUIDType was the addition of the method:

@Override
protected boolean registerUnderJavaType() {
    // register this type under UUID when it is added to the basic type registry
    return true;
}

which i presume defaults the handling of Java UUID's to the PostgreSQL's native UUID type. This change was make specifically in Hibernate 5 (https://hibernate.atlassian.net/browse/HHH-9577)

My question is how do i get back Hibernate 4 behavior back as we already have an existing database schema in place.

Thank you.

UPDATE

I found the migration guide documented here: https://github.com/hibernate/hibernate-orm/blob/5.0/migration-guide.adoc

it states the following:

For ids defined as UUID with generation, for some databases it is required to explicitly set the @Column( length=16 ) in order to generate BINARY(16) so that comparisons properly work.

I tried this and still no change in behavior.

Upvotes: 3

Views: 3821

Answers (2)

federicojasson
federicojasson

Reputation: 382

In case you have a lot of UUID attributes as I did, you could use a @TypeDef annotation at the package level (in a package-info.java file), as:

// Forces UUID attributes to be mapped as binary columns (for backward-compatibility)
@TypeDef(defaultForType = UUID.class, typeClass = UUIDBinaryType.class)
package <your top-level package>;

import org.hibernate.annotations.TypeDef;
import org.hibernate.type.UUIDBinaryType;

import java.util.UUID;

It's not the cleanest solution, but it avoids having to change each and every UUID attribute.

Upvotes: 2

loesak
loesak

Reputation: 1613

I believe I found the solution. I needed to now mark my UUID types with type "uuid-binary". Verified that this generates they type as bytea in Postgres and that i can read records from my existing database.

@Id
@GeneratedValue(generator = "uuid2")
@GenericGenerator(name = "uuid2", strategy = "uuid2")
@Type(type = "uuid-binary")
private UUID id;

Upvotes: 1

Related Questions