Hibernate支持Postgresql UUID?

我不能让Hibernate使用java.util.UUID for PostgreSQL。

这是使用javax.persistence的映射。* annotations:

private UUID itemUuid; @Column(name="item_uuid",columnDefinition="uuid NOT NULL") public UUID getItemUuid() { return itemUuid; } public void setItemUuid(UUID itemUuid) { this.itemUuid = itemUuid; } 

当持久化对象时,我得到一个SQLGrammarException:

 column "item_uuid" is of type uuid but expression is of type bytea at character 149 

PostgreSQL版本是8.4.4
JDBC驱动程序 – 8.4.4-702(也试过9.0 – 同样的事情)
Hibernate版本是3.6,主要配置属性:

 org.hibernate.dialect.PostgreSQLDialect org.postgresql.Driver jdbc:postgresql://192.168.1.1/db_test 

这可以通过向UUID添加以下注释来解决:

 import org.hibernate.annotations.Type; ... @Type(type="pg-uuid") private java.util.UUID itemUuid; 

至于为什么Hibernate不只是将它设为默认设置,我无法告诉你……

更新:使用createNativeQuery方法打开具有UUID字段的对象似乎仍然存在问题。 幸运的是,到目前为止,createQuery方法对我来说很好。

您尝试持久化UUID类型的对象,这不是带有hibernate注释的实体。 所以hibernate想要将它序列化为字节数组(blob类型)。 这就是为什么你得到这个消息’类型为bytea’的表达式。

您可以将UUID作为blob存储在数据库中(不是优雅的),或者提供自定义序列化程序(很多工作)或手动转换该对象。 UUID类有fromString和toString方法,所以我将它存储为String。

正如其他人提到的,这个问题的解决方案是添加@Type(type = "pg-uuid")注释。 但是,此类型与其他供应商的UUID类型不兼容,因此这将您的Hibernate类与Postgres联系起来。 要解决此问题,可以在运行时插入此批注。 以下适用于Hibernate 4.3.7。

首先,您需要插入自定义元数据提供程序以插入注释。 这是创建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())); } 

此自定义元数据提供程序查找UUID类型的字段和方法。 如果找到一个,它会插入一个org.hibernate.annotations.Type注释的实例,声明该类型应为"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 getDefaults() { return delegate.getDefaults(); } @Override public AnnotationReader getAnnotationReader(AnnotatedElement annotatedElement) { // This method is called a lot of times on the same element, so annotation // readers are cached. We only cache our readers because the provider // we delegate to also caches them. AnnotationReader reader = cache.get(annotatedElement); if (reader != null) { return reader; } reader = delegate.getAnnotationReader(annotatedElement); // If this element is a method that returns a UUID, or a field of type UUID, // wrap the returned reader in a new reader that inserts the "pg-uuid" Type // annotation. boolean isUuid = false; if (annotatedElement instanceof Method) { isUuid = ((Method)annotatedElement).getReturnType() == UUID.class; } else if (annotatedElement instanceof Field) { isUuid = ((Field)annotatedElement).getType() == UUID.class; } if (isUuid) { reader = new UUIDTypeInserter(reader); cache.put(annotatedElement, reader); } return reader; } private static class UUIDTypeInserter implements AnnotationReader { private static final Type INSTANCE = new Type() { @Override public Class annotationType() { return Type.class; } @Override public String type() { return "pg-uuid"; } @Override public Parameter[] parameters() { return new Parameter[0]; } }; private final AnnotationReader delegate; public UUIDTypeInserter(AnnotationReader delegate) { this.delegate = delegate; } @Override @SuppressWarnings("unchecked") public  T getAnnotation(Class annotationType) { if (annotationType == Type.class) { return (T)INSTANCE; } return delegate.getAnnotation(annotationType); } @Override public  boolean isAnnotationPresent(Class annotationType) { return annotationType == Type.class || delegate.isAnnotationPresent(annotationType); } @Override public Annotation[] getAnnotations() { Annotation[] annotations = delegate.getAnnotations(); Annotation[] result = Arrays.copyOf(annotations, annotations.length + 1); result[result.length - 1] = INSTANCE; return result; } } } 

不使用JPA的人的解决方案。

之前:

    

后: