Search code examples
javapostgresqljpaeclipselinkjpa-2.0

Using UUID with EclipseLink and PostgreSQL


I want to use the PostgreSQL uuid type for objects' primary keys. For that I've created a converter (implementing the Converter interface). Bellow is the relevant code:

    @Override
    public void initialize(DatabaseMapping mapping, Session session) {
        final DatabaseField field;
        if (mapping instanceof DirectCollectionMapping) {
            field = ((DirectCollectionMapping) mapping).getDirectField();
        } else {
            field = mapping.getField();
        }

        field.setSqlType(Types.OTHER);
        field.setTypeName("uuid");
        field.setColumnDefinition("UUID");
    }

Then I've annotated the relevant entity X with the bellow annotations:

@Converter(name="uuidConverter",converterCalss=UUIDConverter.class)
@Convert("uuidConverter")
@Id
public UUID getId()
{
    return id;
}

The problem is that I have another class (Y) which has the following definition:

@ManyToOne(targetEntity = X.class)
@JoinColumn(name = "x_id")
public X getX();

Although EclipseLink created the tables as expected it sends a string to the database when trying to insert objects of type Y. Postgres returns the following error message:

column "id" is of type uuid but expression is of type character varying at character

Any solutions / work around will be appreciated.


Solution

  • I had the same issue with EclipseLink JPA + Postgresql + UUID as primary key.

    To solve it, I've merged codes from Github and below link: https://forums.oracle.com/forums/thread.jspa?messageID=4584157

    The below code for UUIDConverter worked for me, though the code surely isn't the best.

    public void initialize(DatabaseMapping ARGMapping, Session ARGSession)
    {
        final DatabaseField Field;
        if (ARGMapping instanceof DirectCollectionMapping)
        {
            Field = ((DirectCollectionMapping) ARGMapping).getDirectField();
        }
        else
        {
            Field = ARGMapping.getField();
        }
        Field.setSqlType(Types.OTHER);
        Field.setTypeName("uuid");
        Field.setColumnDefinition("UUID");
    
        for (DatabaseMapping m : ARGMapping.getDescriptor().getMappings())
        {
            assert OneToOneMapping.class.isAssignableFrom(ManyToOneMapping.class);
            if (m instanceof OneToOneMapping)
            {
                for (DatabaseField field : ((OneToOneMapping) m).getForeignKeyFields())
                {
                    field.setSqlType(Types.OTHER);
                    field.setColumnDefinition("UUID");
                    field.setTypeName("uuid");
                }
            }
        }
    }