Home > Enterprise >  How to retrieve UUID value in Java/JPA for Oracle database?
How to retrieve UUID value in Java/JPA for Oracle database?

Time:02-15

I am using Oracle database and have to define a UUID column. I followed other posts and created the table using regex pattern for primary key:

CREATE TABLE TEST_UUID (
    ID_UUID VARCHAR(255)
    DEFAULT REGEXP_REPLACE(RAWTOHEX(SYS_GUID()), '([A-F0-9]{8})([A-F0-9]{4})([A-F0-9]{4})([A-F0-9]{4})([A-F0-9]{12})', '\1-\2-\3-\4-\5'),
    NAME VARCHAR2(40)  NOT NULL
);

In my entity class I have to define the ID_UUID column of type UUID (cannot define it as String). The entity class looks like this:

import java.util.UUID;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "test_uuid")
public class TestUuid {

    @Id
    @Column(name = "id_uuid")
    @GeneratedValue(strategy = GenerationType.AUTO)
    private UUID idUuid;

    @Column(name = "name")
    private String name;

    /**
     * @return the idUuid
     */
    public UUID getIdUuid() {
        return idUuid;
    }

    /**
     * @param idUuid the idUuid to set
     */
    public void setIdUuid(UUID idUuid) {
        this.idUuid = idUuid;
    }

    /**
     * @return the name
     */
    public String getName() {
        return name;
    }

    /**
     * @param name the name to set
     */
    public void setName(String name) {
        this.name = name;
    }

}

When I retrieve the table values I don't get the same value for ID_UUID whats stored in the database because of UUID data type (if I change it to a String I am able to pull the correct value). My limitation is to use the UUID type as I am migrating from Postgre to Oracle database and cannot change my entity class. Is it possible to retrieve the correct value using UUID data type?

CodePudding user response:

You need to define custom type that stores and retrieves UUID type as VARCHAR.

See Hibernate UUID type implementation.
https://github.com/hibernate/hibernate-orm/blob/main/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/UUIDJavaType.java
In case if you have Hibernate 5 or higher you can use it.

  1. Create own user type
public class UUIDType extends AbstractSingleColumnStandardBasicType<UUID> {

    public static final UUIDType INSTANCE = new UUIDType();
    public static final String NAME = "UUIDType";

    public UUIDType() {
        super(VarcharTypeDescriptor.INSTANCE, UUIDTypeDescriptor.INSTANCE);
    }

    @Override
    public String getName() {
        return NAME;
    }
}
  1. Implement a UUIDTypeDescriptor for storing and retrieving UUID as VARCHAR
public class UUIDTypeDescriptor extends AbstractTypeDescriptor<UUID> {

    public static final UUIDTypeDescriptor INSTANCE = new UUIDTypeDescriptor();

    public UUIDTypeDescriptor() {
        super(UUID.class, ImmutableMutabilityPlan.INSTANCE);
    }

    @Override
    public String toString(UUID uuid) {
        return uuid.toString();
    }

    @Override
    public UUID fromString(String s) {
        return UUID.fromString(s);
    }

    @Override
    public <T> T unwrap(UUID uuid, Class<T> type, WrapperOptions wrapperOptions) {
        if (uuid == null) return null;

        if (String.class.isAssignableFrom(type)) {
            return (T) uuid.toString();
        }

        throw unknownUnwrap(type);
    }

    @Override
    public <T> UUID wrap(T value, WrapperOptions wrapperOptions) {
        if (value == null)
            return null;

        if(value instanceof String) {
            return UUID.fromString((String) value);
        }

        throw unknownWrap(value.getClass());
    }
}
  1. Apply custom type to your entity

Specific for entity:

@TypeDef(name = UUIDType.NAME, 
         typeClass = UUIDType.class,
         defaultForType = UUID.class)
@Entity
@Table(name = "test_uuid")
public class TestUUID {

}

or on package lavel in package-info.java file:

@TypeDef(
    name = UUIDType.NAME,
    typeClass = UUIDType.class,
    defaultForType = UUID.class
)
package com.model;
  • Related