No puedo hacer que Hibernate trabaje con java.utiliránID para PostgreSQL.
Aquí está el mapeo usando las anotaciones javax.persistence. *:
private UUID itemUuid; @Column(name="item_uuid",columnDefinition="uuid NOT NULL") public UUID getItemUuid() { return itemUuid; } public void setItemUuid(UUID itemUuid) { this.itemUuid = itemUuid; }
Al persistir un objeto transitorio obtengo una SQLGrammarException:
column "item_uuid" is of type uuid but expression is of type bytea at character 149
La versión de PostgreSQL es 8.4.4
Controlador JDBC – 8.4.4-702 (también intenté 9.0 – lo mismo)
La versión de Hibernate es 3.6, propiedades principales de configuración:
org.hibernate.dialect.PostgreSQLDialect org.postgresql.Driver jdbc:postgresql://192.168.1.1/db_test
Esto se puede resolver agregando la siguiente anotación al UUID:
import org.hibernate.annotations.Type; ... @Type(type="pg-uuid") private java.util.UUID itemUuid;
En cuanto a por qué Hibernate no solo hace de esto la configuración predeterminada, no podría decirte …
ACTUALIZACIÓN: Todavía parece haber problemas con el método createNativeQuery para abrir objetos que tienen campos UUID. Afortunadamente, el método createQuery hasta ahora me ha funcionado bien.
Intenta persistir el objeto de tipo UUID, que no es una entidad con hibernación anotada. Entonces, el hibernate quiere serializarlo en una matriz de bytes (tipo blob). Es por eso que recibes este mensaje ‘expresión de tipo bytea’.
Puede almacenar UUID como blobs en la base de datos (no elegante), o proporcionar su serializador personalizado (mucho trabajo) o convertir manualmente ese objeto. La clase UUID tiene métodos fromString y toString, por lo que lo almacenaría como String.
Como mencionaron otros, la solución a este problema es agregar una @Type(type = "pg-uuid")
. Sin embargo, este tipo no es compatible con los tipos UUID de otros proveedores, por lo que esto vincula sus clases Hibernate a Postgres. Para solucionar esto, es posible insertar esta anotación en tiempo de ejecución. El siguiente funciona para Hibernate 4.3.7.
En primer lugar, debe insertar un proveedor de metadatos personalizado para insertar las anotaciones. Haga esto como el primer paso después de crear una instancia de la clase de Configuration
:
// Perform some test to verify that the current database is Postgres. if (connectionString.startsWith("jdbc:postgresql:")) { // Replace the metadata provider with our custom metadata provider. MetadataProviderInjector reflectionManager = MetadataProviderInjector)cfg.getReflectionManager(); reflectionManager.setMetadataProvider(new UUIDTypeInsertingMetadataProvider(reflectionManager.getMetadataProvider())); }
Este proveedor de metadatos personalizado busca campos y métodos de tipo UUID
. Si encuentra uno, inserta una instancia de la anotación org.hibernate.annotations.Type
que indica que el tipo debe ser "pg-uuid"
:
package nl.gmt.data; import org.hibernate.annotations.Parameter; import org.hibernate.annotations.Type; import org.hibernate.annotations.common.reflection.AnnotationReader; import org.hibernate.annotations.common.reflection.MetadataProvider; import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.UUID; class UUIDTypeInsertingMetadataProvider implements MetadataProvider { private final Map cache = new HashMap<>(); private final MetadataProvider delegate; public UUIDTypeInsertingMetadataProvider(MetadataProvider delegate) { this.delegate = delegate; } @Override public Map
Solución para alguien que no usa JPA.
Antes de:
Después: