Postgresql UUID supported by Hibernate?

前端 未结 5 1385
悲哀的现实
悲哀的现实 2020-11-27 07:28

I can\'t get Hibernate working with java.util.UUID for PostgreSQL.

Here is the mapping using javax.persistence.* annotations:

private UUID itemUuid;
         


        
5条回答
  •  甜味超标
    2020-11-27 07:47

    As others mentioned, the solution to this issue is to add a @Type(type = "pg-uuid") annotation. However, this type is not compatible with UUID types of other vendors, so this ties your Hibernate classes to Postgres. To work around this, it is possible to insert this annotation at runtime. The below works for Hibernate 4.3.7.

    First, you need to insert a custom metadata provider to insert the annotations. Do this as the first step after creating an instance of the Configuration class:

    // 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()));
    }
    

    This custom metadata provider finds fields and methods of type UUID. If it finds one, it inserts an instance of the org.hibernate.annotations.Type annotation stating that the type should be "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;
            }
        }
    }
    

提交回复
热议问题